|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Fields in Interfaces, IndexerI 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]; } } } } 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]; } > } > } > } > > 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)? |
|||||||||||||||||||||||