Home All Groups Group Topic Archive Search About

Fields in Interfaces, Indexer

Author
15 Feb 2007 10:09 PM
hufaunder@yahoo.com
SITUATION:
I have a class "MainClass" that has an indexer "SubClass1Indexer".
This indexer returns an instance that implements a particular
interface "ISubClass1". This interface defines another indexer
"SubClass2Indexer". Bellow is some code with comments. It should
compile.

PROBLEM:
I would like to write something like this:

      MainClass cm = new MainClass();
      cm.SubClass1Values[0].SubClass2Values[0].ToString();

Note that "SubClass2Indexer" needs access to an internal field of
"SubClass1". This only seems to be possible if a field is allowed in
an interface, i.e. ISubClass1. That is not the case, though.

NONE IDEAL SOLUTIONS:
1) Make "this[]" in SubClass2Indexer aware of all the current and
future implementations of "ISubClass1".
2) Do a casting after "cm.SubClass1Values[0]" but then I have to write
separate indexers "SubClass2Indexer" for each implementation of
"ISubClass1".

QUESTION:
How can I solve the shortcomings in the above solutions? Or in general
how is this best handled?

CODE:
using System;
using System.Collections.Generic;
using System.Text;

namespace testProj
{
    class Program
    {
        static void Main(string[] args)
        {
            MainClass cm = new MainClass();
            cm.SubClass1Values[0].SubClass2Values[0].ToString();
        }
    }

    //CLASSES
    public class MainClass
    {
        private SubClass1Indexer m_subClass1Indexer;
        protected internal List<ISubClass1> m_subClass1List; //
SubClass1Indexer needs access to this.

        public SubClass1Indexer SubClass1Values
        {
            get { return m_subClass1Indexer; }
        }
    }

    public class SubClass1 : ISubClass1
    {
        private SubClass2Indexer m_subClass2Indexer;
        protected internal List<ISubClass2> m_subClass2List; //
SubClass2Indexer needs access to this.

        public SubClass2Indexer SubClass2Values
        {
            get { return m_subClass2Indexer; }
        }
    }

    //INTERFACES
    public interface ISubClass1
    {
        //!!! If the following would be possible then in
SubClass2Indexer
        // I would not have to make the function 'this[]' be aware of
all
        // the ISubClass1 implementations.
        //protected internal List<ISubClass> m_subClass2List;

        SubClass2Indexer SubClass2Values { get; }
    }

    public interface ISubClass2
    {
    }

    //INDEXERS
    public class SubClass1Indexer
    {
        private readonly MainClass m_subClass1Owner;

        public SubClass1Indexer(MainClass seriesOwner)
        {
            m_subClass1Owner = seriesOwner;
        }

        public ISubClass1 this[Int32 index]
        {
            get {
                return m_subClass1Owner.m_subClass1List[index];
            }
        }
    }

    public class SubClass2Indexer
    {
        private readonly ISubClass1 m_subClass2Owner;

        public SubClass2Indexer(ISubClass1 subClass2Owner)
        {
            m_subClass2Owner = subClass2Owner;
        }

        public ISubClass2 this[Int32 index]
        {
            //The command commented out would be possible if one could
            // define a field in an interface. Now I'll need a switch
            // to handle all the IClass1 implementations. So I can't
just
            // add a new implementation without adjusting this
function.
            //get { return m_subClass2Owner.m_subClass2List[index]; }
            get { return
((SubClass1)m_subClass2Owner).m_subClass2List[index]; }
        }
    }
}

Author
16 Feb 2007 12:57 PM
Ciaran O''Donnell
Your structure is confusing which means there may be a simpler design.
However, I think you should be able to solve the issue by giving
SubClass1Indexer a constructor that took a List<ISubClass1> rather than a
MainClass.

Post again if this doesnt work out.

Show quote
"hufaun***@yahoo.com" wrote:

> SITUATION:
> I have a class "MainClass" that has an indexer "SubClass1Indexer".
> This indexer returns an instance that implements a particular
> interface "ISubClass1". This interface defines another indexer
> "SubClass2Indexer". Bellow is some code with comments. It should
> compile.
>
> PROBLEM:
> I would like to write something like this:
>
>       MainClass cm = new MainClass();
>       cm.SubClass1Values[0].SubClass2Values[0].ToString();
>
> Note that "SubClass2Indexer" needs access to an internal field of
> "SubClass1". This only seems to be possible if a field is allowed in
> an interface, i.e. ISubClass1. That is not the case, though.
>
> NONE IDEAL SOLUTIONS:
> 1) Make "this[]" in SubClass2Indexer aware of all the current and
> future implementations of "ISubClass1".
> 2) Do a casting after "cm.SubClass1Values[0]" but then I have to write
> separate indexers "SubClass2Indexer" for each implementation of
> "ISubClass1".
>
> QUESTION:
> How can I solve the shortcomings in the above solutions? Or in general
> how is this best handled?
>
> CODE:
> using System;
> using System.Collections.Generic;
> using System.Text;
>
> namespace testProj
> {
>     class Program
>     {
>         static void Main(string[] args)
>         {
>             MainClass cm = new MainClass();
>             cm.SubClass1Values[0].SubClass2Values[0].ToString();
>         }
>     }
>
>     //CLASSES
>     public class MainClass
>     {
>         private SubClass1Indexer m_subClass1Indexer;
>         protected internal List<ISubClass1> m_subClass1List; //
> SubClass1Indexer needs access to this.
>
>         public SubClass1Indexer SubClass1Values
>         {
>             get { return m_subClass1Indexer; }
>         }
>     }
>
>     public class SubClass1 : ISubClass1
>     {
>         private SubClass2Indexer m_subClass2Indexer;
>         protected internal List<ISubClass2> m_subClass2List; //
> SubClass2Indexer needs access to this.
>
>         public SubClass2Indexer SubClass2Values
>         {
>             get { return m_subClass2Indexer; }
>         }
>     }
>
>     //INTERFACES
>     public interface ISubClass1
>     {
>         //!!! If the following would be possible then in
> SubClass2Indexer
>         // I would not have to make the function 'this[]' be aware of
> all
>         // the ISubClass1 implementations.
>         //protected internal List<ISubClass> m_subClass2List;
>
>         SubClass2Indexer SubClass2Values { get; }
>     }
>
>     public interface ISubClass2
>     {
>     }
>
>     //INDEXERS
>     public class SubClass1Indexer
>     {
>         private readonly MainClass m_subClass1Owner;
>
>         public SubClass1Indexer(MainClass seriesOwner)
>         {
>             m_subClass1Owner = seriesOwner;
>         }
>
>         public ISubClass1 this[Int32 index]
>         {
>             get {
>                 return m_subClass1Owner.m_subClass1List[index];
>             }
>         }
>     }
>
>     public class SubClass2Indexer
>     {
>         private readonly ISubClass1 m_subClass2Owner;
>
>         public SubClass2Indexer(ISubClass1 subClass2Owner)
>         {
>             m_subClass2Owner = subClass2Owner;
>         }
>
>         public ISubClass2 this[Int32 index]
>         {
>             //The command commented out would be possible if one could
>             // define a field in an interface. Now I'll need a switch
>             // to handle all the IClass1 implementations. So I can't
> just
>             // add a new implementation without adjusting this
> function.
>             //get { return m_subClass2Owner.m_subClass2List[index]; }
>             get { return
> ((SubClass1)m_subClass2Owner).m_subClass2List[index]; }
>         }
>     }
> }
>
>
Author
16 Feb 2007 5:07 PM
hufaunder@yahoo.com
Ciaran,

That indeed seems to be a solution. The reason I was passing MainClass
to the ctr of SubClass1Indexer is because samples from MSDN and
CodeProject both did it this way. See here:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/vcwlkIndexedPropertiesTutorial.asp

Class WordCollection is the indexer and it's constructor takes the
parent class Document. MSDN says: "For each "indexed property," you
define a nested class, which contains a reference back to the main
class instance."

Is there a reason why most people do it this way and not the way you
suggested (which seems to work better for me)?

AddThis Social Bookmark Button