Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Collections, plus collection of base type - concept

Collections, plus collection of base type - concept

Scheduled Pinned Locked Moved C#
csharpcomfunctionalquestion
19 Posts 4 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    DaveyM69
    wrote on last edited by
    #1

    I have an abstract base class and two derived classes:- MyBase, MyFoo : MyBase, MyBar : MyBase. I am creating readonly (and immutable) collections of MyFoo and MyBar:- MyFooCollection, MyBarCollection. These are created by a one shot only factory method, so once instanciated the collection's contents will not change. I would also like to provide, for convenience, a collection of MyBase:- MyBaseCollection which is a collation of all items in the other collections. What would be your preferred method? A. Create a MyBaseCollection on the fly each time it requested from the existing two collections. B. Cache a MyBaseCollection and even though it is a duplication of the existing two collections. C. Cache only a MyBaseCollection and create the other two collections on the fly from it. D. Something else...

    Dave
    Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
    BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

    P B 2 Replies Last reply
    0
    • D DaveyM69

      I have an abstract base class and two derived classes:- MyBase, MyFoo : MyBase, MyBar : MyBase. I am creating readonly (and immutable) collections of MyFoo and MyBar:- MyFooCollection, MyBarCollection. These are created by a one shot only factory method, so once instanciated the collection's contents will not change. I would also like to provide, for convenience, a collection of MyBase:- MyBaseCollection which is a collation of all items in the other collections. What would be your preferred method? A. Create a MyBaseCollection on the fly each time it requested from the existing two collections. B. Cache a MyBaseCollection and even though it is a duplication of the existing two collections. C. Cache only a MyBaseCollection and create the other two collections on the fly from it. D. Something else...

      Dave
      Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
      BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

      P Offline
      P Offline
      PIEBALDconsult
      wrote on last edited by
      #2

      What do you need to do with it? If you're only going to iterate over it (foreach), then I suggest a simple iterator that iterates one then the other -- the caller could cache the results if needed.

      D 1 Reply Last reply
      0
      • P PIEBALDconsult

        What do you need to do with it? If you're only going to iterate over it (foreach), then I suggest a simple iterator that iterates one then the other -- the caller could cache the results if needed.

        D Offline
        D Offline
        DaveyM69
        wrote on last edited by
        #3

        They are part of a class library. They implement IEnumerable<T> to provide the itterator over a private inner List<T>. That is really all they will expose apart from an indexer with getter only. So, create a IEnumerable<MyBase> or MyBaseCollection the first time it's needed and cache it in case it's needed in future?

        Dave
        Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
        BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

        P L 2 Replies Last reply
        0
        • D DaveyM69

          They are part of a class library. They implement IEnumerable<T> to provide the itterator over a private inner List<T>. That is really all they will expose apart from an indexer with getter only. So, create a IEnumerable<MyBase> or MyBaseCollection the first time it's needed and cache it in case it's needed in future?

          Dave
          Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
          BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

          P Offline
          P Offline
          PIEBALDconsult
          wrote on last edited by
          #4

          Here's a little something I whipped up to experiment. A base class, two derived classes, and a list for each derived class:

          private class C
          {
          public string Name { get ; private set ; }

          public C ( string Name ) { this.Name = Name ; }

          public override string ToString() { return ( this.Name ) ; }
          }

          private class A : C
          {
          public A ( string Name ) : base ( Name ) {}
          }

          private class B : C
          {
          public B ( string Name ) : base ( Name ) {}
          }

          private static System.Collections.Generic.List<A> alist = new System.Collections.Generic.List<A>() ;
          private static System.Collections.Generic.List<B> blist = new System.Collections.Generic.List<B>() ;

          An enumerator (or is it an iterator?) -- I think it would be in your base class and probably not take parameters:

          private static System.Collections.Generic.IEnumerable<C>
          All
          (
          params System.Collections.Generic.IEnumerable<C>[] lists
          )
          {
          foreach ( System.Collections.Generic.IEnumerable<C> l in lists )
          {
          foreach ( C c in l )
          {
          yield return ( c ) ;
          }
          }

          yield break ;
          }

          Then I can call it:

          foreach ( C c in All ( alist , blist ) )
          {
          System.Console.WriteLine ( c ) ;
          }

          The code that does this could choose to cache the results if it needs to.

          D 1 Reply Last reply
          0
          • P PIEBALDconsult

            Here's a little something I whipped up to experiment. A base class, two derived classes, and a list for each derived class:

            private class C
            {
            public string Name { get ; private set ; }

            public C ( string Name ) { this.Name = Name ; }

            public override string ToString() { return ( this.Name ) ; }
            }

            private class A : C
            {
            public A ( string Name ) : base ( Name ) {}
            }

            private class B : C
            {
            public B ( string Name ) : base ( Name ) {}
            }

            private static System.Collections.Generic.List<A> alist = new System.Collections.Generic.List<A>() ;
            private static System.Collections.Generic.List<B> blist = new System.Collections.Generic.List<B>() ;

            An enumerator (or is it an iterator?) -- I think it would be in your base class and probably not take parameters:

            private static System.Collections.Generic.IEnumerable<C>
            All
            (
            params System.Collections.Generic.IEnumerable<C>[] lists
            )
            {
            foreach ( System.Collections.Generic.IEnumerable<C> l in lists )
            {
            foreach ( C c in l )
            {
            yield return ( c ) ;
            }
            }

            yield break ;
            }

            Then I can call it:

            foreach ( C c in All ( alist , blist ) )
            {
            System.Console.WriteLine ( c ) ;
            }

            The code that does this could choose to cache the results if it needs to.

            D Offline
            D Offline
            DaveyM69
            wrote on last edited by
            #5

            Interesting - I like it. I can't implement the code in exactly this way as this is a .Net 2 assembly so doesn't support covariance and contravariance, but I can acheive the same thing with a little more code. Thanks :thumbsup: [Edit] As the two existing collections are already stored and I know that's all I'll need I've put it all in a property and harcoded the collections - .NET 2 / C#<4 friendly:

            public IEnumerable All
            {
            get
            {
            foreach (MyBase myBase in MyFooCollection)
            yield return myBase;
            foreach (MyBase myBase in MyBarCollection)
            yield return myBase;
            yield break;
            }
            }

            Dave
            Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
            BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

            P 1 Reply Last reply
            0
            • D DaveyM69

              Interesting - I like it. I can't implement the code in exactly this way as this is a .Net 2 assembly so doesn't support covariance and contravariance, but I can acheive the same thing with a little more code. Thanks :thumbsup: [Edit] As the two existing collections are already stored and I know that's all I'll need I've put it all in a property and harcoded the collections - .NET 2 / C#<4 friendly:

              public IEnumerable All
              {
              get
              {
              foreach (MyBase myBase in MyFooCollection)
              yield return myBase;
              foreach (MyBase myBase in MyBarCollection)
              yield return myBase;
              yield break;
              }
              }

              Dave
              Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
              BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

              P Offline
              P Offline
              PIEBALDconsult
              wrote on last edited by
              #6

              Yes, that's what I imagined would work in your situation. :thumbsup:

              1 Reply Last reply
              0
              • D DaveyM69

                They are part of a class library. They implement IEnumerable<T> to provide the itterator over a private inner List<T>. That is really all they will expose apart from an indexer with getter only. So, create a IEnumerable<MyBase> or MyBaseCollection the first time it's needed and cache it in case it's needed in future?

                Dave
                Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
                BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

                L Offline
                L Offline
                Luc Pattyn
                wrote on last edited by
                #7

                An enumerator has a state ("where am I?") which must be saved somewhere. If its state is inside the collection itself, you probably can't have two independent iterators at once, so things like:

                foreach(someType a in collection) {
                foreach (someType b in collection) {
                if (a!=b) doSomeThingTo(a,b);
                }
                }

                would fail. Having code accessing your collection from different threads through enumerators would fail too. What I'm saying is, most of the time, IEnumerable (i.e. GetEnumerator) requires you to create a new enumerator each time. It is too bad they called it such, CreateEnumerator would have been the better choice. :) PS, FWIW: are you familiar with AsReadOnly?[^]

                Luc Pattyn [My Articles] Nil Volentibus Arduum

                D 2 Replies Last reply
                0
                • L Luc Pattyn

                  An enumerator has a state ("where am I?") which must be saved somewhere. If its state is inside the collection itself, you probably can't have two independent iterators at once, so things like:

                  foreach(someType a in collection) {
                  foreach (someType b in collection) {
                  if (a!=b) doSomeThingTo(a,b);
                  }
                  }

                  would fail. Having code accessing your collection from different threads through enumerators would fail too. What I'm saying is, most of the time, IEnumerable (i.e. GetEnumerator) requires you to create a new enumerator each time. It is too bad they called it such, CreateEnumerator would have been the better choice. :) PS, FWIW: are you familiar with AsReadOnly?[^]

                  Luc Pattyn [My Articles] Nil Volentibus Arduum

                  D Offline
                  D Offline
                  DaveyM69
                  wrote on last edited by
                  #8

                  Good point Luc, thanks. I will look into this further.

                  Luc Pattyn wrote:

                  FWIW: are you familiar with AsReadOnly?

                  Yes I am. The collections need to have internal constructors and an internal Add method so it was just as easy to create a simple base class (not the MyBase referred to in the OP) with this functionality that the other collections derive from.

                  Dave
                  Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
                  BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

                  B 1 Reply Last reply
                  0
                  • D DaveyM69

                    Good point Luc, thanks. I will look into this further.

                    Luc Pattyn wrote:

                    FWIW: are you familiar with AsReadOnly?

                    Yes I am. The collections need to have internal constructors and an internal Add method so it was just as easy to create a simple base class (not the MyBase referred to in the OP) with this functionality that the other collections derive from.

                    Dave
                    Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
                    BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

                    B Offline
                    B Offline
                    BillWoodruff
                    wrote on last edited by
                    #9

                    Hi Davey, If you did not use IList(s) (as Luc suggested) set to some Collection modified by the 'ReadOnly() method, as in:

                    public static IList<MyFoo> MyFoos;
                    //
                    // and later ... after creating and initializing 'MyFooCollection:
                    //
                    MyFoos = MyFooCollection.AsReadOnly();

                    Then I am very curious what technique(s) you did use to make the Collections in your code ReadOnly. thanks, Davey (and Luc)

                    When I consider the brief span of my life, swallowed up in the eternity before and after, the little space which I fill, and even can see, engulfed in the infinite immensity of spaces of which I am ignorant, and which knows me not, I am frightened, and am astonished at being here rather than there; for there is no reason why here rather than there, now rather than then.

                    Blaise Pascal

                    D 1 Reply Last reply
                    0
                    • B BillWoodruff

                      Hi Davey, If you did not use IList(s) (as Luc suggested) set to some Collection modified by the 'ReadOnly() method, as in:

                      public static IList<MyFoo> MyFoos;
                      //
                      // and later ... after creating and initializing 'MyFooCollection:
                      //
                      MyFoos = MyFooCollection.AsReadOnly();

                      Then I am very curious what technique(s) you did use to make the Collections in your code ReadOnly. thanks, Davey (and Luc)

                      When I consider the brief span of my life, swallowed up in the eternity before and after, the little space which I fill, and even can see, engulfed in the infinite immensity of spaces of which I am ignorant, and which knows me not, I am frightened, and am astonished at being here rather than there; for there is no reason why here rather than there, now rather than then.

                      Blaise Pascal

                      D Offline
                      D Offline
                      DaveyM69
                      wrote on last edited by
                      #10

                      Well a simple collection (generic) that is immutable (so naturally read only) just needs to accept items at instanciation, optionaly an indexer with a getter only defined and a count property - and of course implemeting IEnumerable<T> so it can be enumerated. Therefore a simple wrapper around List<T> suffices:

                      public class ImmutableCollection : IEnumerable
                      {
                      private List innerList;

                      public ImmutableCollection(IEnumerable collection)
                      {
                          innerList = new List(collection);
                      }
                      
                      public T this\[int index\]
                      {
                          get { return innerList\[index\]; }
                      }
                      public int Count
                      {
                          get { return innerList.Count; }
                      }
                      
                      public IEnumerator GetEnumerator()
                      {
                          return ((IEnumerable)innerList).GetEnumerator();
                      }
                      IEnumerator IEnumerable.GetEnumerator()
                      {
                          return ((IEnumerable)innerList).GetEnumerator();
                      }
                      

                      }

                      As the innerList is never exposed it is read only :) Usage:

                      ImmutableCollection collection = new ImmutableCollection(new string[] { "A", "B", "C" });

                      Of course, the properties/fields of the the items contained will not be immutable, but that is the same as the ReadOnlyCollection<T> available from .AsReadOnly, but the minimum functionality only is exposed, and whatever you need to add can be created simply by accessing the inner list. If necessary, the inner list could be made protected so it can be accessed directly in derived classes where concrete classes are desired or required.

                      Dave
                      Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
                      BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

                      B L 2 Replies Last reply
                      0
                      • D DaveyM69

                        Well a simple collection (generic) that is immutable (so naturally read only) just needs to accept items at instanciation, optionaly an indexer with a getter only defined and a count property - and of course implemeting IEnumerable<T> so it can be enumerated. Therefore a simple wrapper around List<T> suffices:

                        public class ImmutableCollection : IEnumerable
                        {
                        private List innerList;

                        public ImmutableCollection(IEnumerable collection)
                        {
                            innerList = new List(collection);
                        }
                        
                        public T this\[int index\]
                        {
                            get { return innerList\[index\]; }
                        }
                        public int Count
                        {
                            get { return innerList.Count; }
                        }
                        
                        public IEnumerator GetEnumerator()
                        {
                            return ((IEnumerable)innerList).GetEnumerator();
                        }
                        IEnumerator IEnumerable.GetEnumerator()
                        {
                            return ((IEnumerable)innerList).GetEnumerator();
                        }
                        

                        }

                        As the innerList is never exposed it is read only :) Usage:

                        ImmutableCollection collection = new ImmutableCollection(new string[] { "A", "B", "C" });

                        Of course, the properties/fields of the the items contained will not be immutable, but that is the same as the ReadOnlyCollection<T> available from .AsReadOnly, but the minimum functionality only is exposed, and whatever you need to add can be created simply by accessing the inner list. If necessary, the inner list could be made protected so it can be accessed directly in derived classes where concrete classes are desired or required.

                        Dave
                        Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
                        BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

                        B Offline
                        B Offline
                        BillWoodruff
                        wrote on last edited by
                        #11

                        +5 Thanks for this most enlightening answer !

                        When I consider the brief span of my life, swallowed up in the eternity before and after, the little space which I fill, and even can see, engulfed in the infinite immensity of spaces of which I am ignorant, and which knows me not, I am frightened, and am astonished at being here rather than there; for there is no reason why here rather than there, now rather than then.

                        Blaise Pascal

                        1 Reply Last reply
                        0
                        • D DaveyM69

                          I have an abstract base class and two derived classes:- MyBase, MyFoo : MyBase, MyBar : MyBase. I am creating readonly (and immutable) collections of MyFoo and MyBar:- MyFooCollection, MyBarCollection. These are created by a one shot only factory method, so once instanciated the collection's contents will not change. I would also like to provide, for convenience, a collection of MyBase:- MyBaseCollection which is a collation of all items in the other collections. What would be your preferred method? A. Create a MyBaseCollection on the fly each time it requested from the existing two collections. B. Cache a MyBaseCollection and even though it is a duplication of the existing two collections. C. Cache only a MyBaseCollection and create the other two collections on the fly from it. D. Something else...

                          Dave
                          Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
                          BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

                          B Offline
                          B Offline
                          BillWoodruff
                          wrote on last edited by
                          #12

                          I know I'm late to the party here, but this question, and what's been exposed in the ensuing discussion, has "fit" with some aspects of use of classes I've been exploring. 1. I noted that in one of colleague PieBald's responses, he defined the Lists (alist, blist) that held collections of instances of classes A,B as static, and outside the scope of all three classes, which I found intriguing. 2. It seems to me that you could exploit the fact that each instantiation of Class A or B does invoke the constructor in class C:

                          private abstract class C
                          {
                          public static readonly List<A> alist = new List<A>();
                          public static readonly List<B> blist = new List<B>();
                          public static readonly List<C> clist = new List<C>();

                          public string Name { get; private set; }
                          
                          public C(string Name)
                          {
                              this.Name = Name;
                          
                              clist.Add(this);
                          
                              if(this is A)
                              {
                                  alist.Add(this as A);
                              }
                              else
                              {
                                  blist.Add(this as B);
                              }
                          }
                          
                          public override string ToString() { return (this.Name); }
                          

                          }

                          Using this implementation of Class C, you guarantee that all three lists are updated with each new instantiation of A or B. Disclaimers-Dunno's: 1. don't know if this would play nice with .NET 2.0 2. thread safety ? I've tested this code with the following:

                          A myA1 = new A("a1");
                          A myA2 = new A("a2");
                          B myB1 = new B("b1");
                          B myB2 = new B("b2");
                          
                          foreach (var a in C.alist)
                          {
                              Console.WriteLine("This A's Name is : " + a.Name);
                          }
                          
                          foreach (var b in C.blist)
                          {
                              Console.WriteLine("This B's Name is : " + b.Name);
                          }
                          
                          foreach (var c in C.clist)
                          {
                              Console.WriteLine("This C is a Type: " + c.GetType() + " : Name = " + c.Name);
                          }
                          

                          The results were as expected:

                          This A's Name is : a1
                          This A's Name is : a2
                          This B's Name is : b1
                          This B's Name is : b2
                          This C is a Type: TestImmutable.Form1+A : Name = a1
                          This C is a Type: TestImmutable.Form1+A : Name = a2
                          This C is a Type: TestImmutable.Form1+B : Name = b1
                          This C is a Type: TestImmutable.Form1+B : Name = b2

                          Be happy to have a critique of this approach. thanks, Bill

                          When I consider the brief span of my life, swallowed up in the eternity before and after, the little space which I fill, and even can see, engulfed in the infinite immensity of spaces of whi

                          1 Reply Last reply
                          0
                          • L Luc Pattyn

                            An enumerator has a state ("where am I?") which must be saved somewhere. If its state is inside the collection itself, you probably can't have two independent iterators at once, so things like:

                            foreach(someType a in collection) {
                            foreach (someType b in collection) {
                            if (a!=b) doSomeThingTo(a,b);
                            }
                            }

                            would fail. Having code accessing your collection from different threads through enumerators would fail too. What I'm saying is, most of the time, IEnumerable (i.e. GetEnumerator) requires you to create a new enumerator each time. It is too bad they called it such, CreateEnumerator would have been the better choice. :) PS, FWIW: are you familiar with AsReadOnly?[^]

                            Luc Pattyn [My Articles] Nil Volentibus Arduum

                            D Offline
                            D Offline
                            DaveyM69
                            wrote on last edited by
                            #13

                            How about getting the enumerator of each collection to enumerate both of them? I have knocked up an example of the general outline of my classes, I have used this in the MyFooMyBarPool.MyBases property.

                            using System;
                            using System.Collections;
                            using System.Collections.Generic;

                            public enum BaseType
                            {
                            MyFoo,
                            MyBar
                            }

                            public abstract class MyBase
                            {
                            private BaseType baseType;
                            private string name;

                            internal MyBase(BaseType baseType, string name)
                            {
                                this.baseType = baseType;
                                this.name = name;
                            }
                            
                            public string Name
                            {
                                get { return name; }
                            }
                            
                            public override string ToString()
                            {
                                return string.Format("Type: {0}, Name: {1}", baseType, name);
                            }
                            

                            }

                            public sealed class MyFoo : MyBase
                            {
                            internal MyFoo(string name)
                            : base(BaseType.MyFoo, name)
                            { }
                            }

                            public sealed class MyBar : MyBase
                            {
                            internal MyBar(string name)
                            : base(BaseType.MyBar, name)
                            { }
                            }

                            public class SimpleCollection : IEnumerable
                            {
                            private List innerList;

                            public SimpleCollection(IEnumerable items)
                            {
                                innerList = new List(items);
                            }
                            
                            public T this\[int index\]
                            {
                                get { return innerList\[index\]; }
                            }
                            public int Count
                            {
                                get { return innerList.Count; }
                            }
                            
                            public IEnumerator GetEnumerator()
                            {
                                return innerList.GetEnumerator();
                            }
                            IEnumerator IEnumerable.GetEnumerator()
                            {
                                return innerList.GetEnumerator();
                            }
                            

                            }

                            public class MyFooCollection : SimpleCollection
                            {
                            internal MyFooCollection(IEnumerable myFoos)
                            : base(myFoos)
                            { }
                            }

                            public class MyBarCollection : SimpleCollection
                            {
                            internal MyBarCollection(IEnumerable myBars)
                            : base(myBars)
                            { }
                            }

                            // In my real code this is a singleton so there will only ever be one pool
                            public class MyFooMyBarPool
                            {
                            private MyFooCollection myFooCollection;
                            private MyBarCollection myBarCollection;

                            public MyFooMyBarPool()
                            {
                                // Items and collections are instanciated here only.
                                myFooCollection = new MyFooCollection(new MyFoo\[\] { new MyFoo("A"), new MyFoo("B"), new MyFoo("C") });
                                myBarCollection = new MyBarCollection(new MyBar\[\] { new MyBar("A"), new MyBar("B"), new MyBar("C") });
                            }
                            
                            public IEnumerable MyBases
                            {
                                get
                                {
                                    IEnumerator myFooEnumer
                            
                            L 3 Replies Last reply
                            0
                            • D DaveyM69

                              Well a simple collection (generic) that is immutable (so naturally read only) just needs to accept items at instanciation, optionaly an indexer with a getter only defined and a count property - and of course implemeting IEnumerable<T> so it can be enumerated. Therefore a simple wrapper around List<T> suffices:

                              public class ImmutableCollection : IEnumerable
                              {
                              private List innerList;

                              public ImmutableCollection(IEnumerable collection)
                              {
                                  innerList = new List(collection);
                              }
                              
                              public T this\[int index\]
                              {
                                  get { return innerList\[index\]; }
                              }
                              public int Count
                              {
                                  get { return innerList.Count; }
                              }
                              
                              public IEnumerator GetEnumerator()
                              {
                                  return ((IEnumerable)innerList).GetEnumerator();
                              }
                              IEnumerator IEnumerable.GetEnumerator()
                              {
                                  return ((IEnumerable)innerList).GetEnumerator();
                              }
                              

                              }

                              As the innerList is never exposed it is read only :) Usage:

                              ImmutableCollection collection = new ImmutableCollection(new string[] { "A", "B", "C" });

                              Of course, the properties/fields of the the items contained will not be immutable, but that is the same as the ReadOnlyCollection<T> available from .AsReadOnly, but the minimum functionality only is exposed, and whatever you need to add can be created simply by accessing the inner list. If necessary, the inner list could be made protected so it can be accessed directly in derived classes where concrete classes are desired or required.

                              Dave
                              Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
                              BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

                              L Offline
                              L Offline
                              Luc Pattyn
                              wrote on last edited by
                              #14

                              encapsulation :)

                              Luc Pattyn [My Articles] Nil Volentibus Arduum

                              1 Reply Last reply
                              0
                              • D DaveyM69

                                How about getting the enumerator of each collection to enumerate both of them? I have knocked up an example of the general outline of my classes, I have used this in the MyFooMyBarPool.MyBases property.

                                using System;
                                using System.Collections;
                                using System.Collections.Generic;

                                public enum BaseType
                                {
                                MyFoo,
                                MyBar
                                }

                                public abstract class MyBase
                                {
                                private BaseType baseType;
                                private string name;

                                internal MyBase(BaseType baseType, string name)
                                {
                                    this.baseType = baseType;
                                    this.name = name;
                                }
                                
                                public string Name
                                {
                                    get { return name; }
                                }
                                
                                public override string ToString()
                                {
                                    return string.Format("Type: {0}, Name: {1}", baseType, name);
                                }
                                

                                }

                                public sealed class MyFoo : MyBase
                                {
                                internal MyFoo(string name)
                                : base(BaseType.MyFoo, name)
                                { }
                                }

                                public sealed class MyBar : MyBase
                                {
                                internal MyBar(string name)
                                : base(BaseType.MyBar, name)
                                { }
                                }

                                public class SimpleCollection : IEnumerable
                                {
                                private List innerList;

                                public SimpleCollection(IEnumerable items)
                                {
                                    innerList = new List(items);
                                }
                                
                                public T this\[int index\]
                                {
                                    get { return innerList\[index\]; }
                                }
                                public int Count
                                {
                                    get { return innerList.Count; }
                                }
                                
                                public IEnumerator GetEnumerator()
                                {
                                    return innerList.GetEnumerator();
                                }
                                IEnumerator IEnumerable.GetEnumerator()
                                {
                                    return innerList.GetEnumerator();
                                }
                                

                                }

                                public class MyFooCollection : SimpleCollection
                                {
                                internal MyFooCollection(IEnumerable myFoos)
                                : base(myFoos)
                                { }
                                }

                                public class MyBarCollection : SimpleCollection
                                {
                                internal MyBarCollection(IEnumerable myBars)
                                : base(myBars)
                                { }
                                }

                                // In my real code this is a singleton so there will only ever be one pool
                                public class MyFooMyBarPool
                                {
                                private MyFooCollection myFooCollection;
                                private MyBarCollection myBarCollection;

                                public MyFooMyBarPool()
                                {
                                    // Items and collections are instanciated here only.
                                    myFooCollection = new MyFooCollection(new MyFoo\[\] { new MyFoo("A"), new MyFoo("B"), new MyFoo("C") });
                                    myBarCollection = new MyBarCollection(new MyBar\[\] { new MyBar("A"), new MyBar("B"), new MyBar("C") });
                                }
                                
                                public IEnumerable MyBases
                                {
                                    get
                                    {
                                        IEnumerator myFooEnumer
                                
                                L Offline
                                L Offline
                                Luc Pattyn
                                wrote on last edited by
                                #15

                                Sorry Dave, it's too early a day to study all that in any detail. As I didn't see any new or Create in there (I may have overlooked them), I doubt it can be correct. If you want to offer simultaneous iterator-like operations to a collection, then the state of the iterator is bound to be outside said collection. You can simply test using this:

                                int count1=0;
                                foreach(someType element in collection) count1++;

                                int count2=0;
                                foreach(someType element1 in collection) {
                                foreach(someType element2 in collection) {
                                count2++;
                                }
                                }
                                if (count2!=count1*count1) noGood();

                                :)

                                Luc Pattyn [My Articles] Nil Volentibus Arduum

                                1 Reply Last reply
                                0
                                • D DaveyM69

                                  How about getting the enumerator of each collection to enumerate both of them? I have knocked up an example of the general outline of my classes, I have used this in the MyFooMyBarPool.MyBases property.

                                  using System;
                                  using System.Collections;
                                  using System.Collections.Generic;

                                  public enum BaseType
                                  {
                                  MyFoo,
                                  MyBar
                                  }

                                  public abstract class MyBase
                                  {
                                  private BaseType baseType;
                                  private string name;

                                  internal MyBase(BaseType baseType, string name)
                                  {
                                      this.baseType = baseType;
                                      this.name = name;
                                  }
                                  
                                  public string Name
                                  {
                                      get { return name; }
                                  }
                                  
                                  public override string ToString()
                                  {
                                      return string.Format("Type: {0}, Name: {1}", baseType, name);
                                  }
                                  

                                  }

                                  public sealed class MyFoo : MyBase
                                  {
                                  internal MyFoo(string name)
                                  : base(BaseType.MyFoo, name)
                                  { }
                                  }

                                  public sealed class MyBar : MyBase
                                  {
                                  internal MyBar(string name)
                                  : base(BaseType.MyBar, name)
                                  { }
                                  }

                                  public class SimpleCollection : IEnumerable
                                  {
                                  private List innerList;

                                  public SimpleCollection(IEnumerable items)
                                  {
                                      innerList = new List(items);
                                  }
                                  
                                  public T this\[int index\]
                                  {
                                      get { return innerList\[index\]; }
                                  }
                                  public int Count
                                  {
                                      get { return innerList.Count; }
                                  }
                                  
                                  public IEnumerator GetEnumerator()
                                  {
                                      return innerList.GetEnumerator();
                                  }
                                  IEnumerator IEnumerable.GetEnumerator()
                                  {
                                      return innerList.GetEnumerator();
                                  }
                                  

                                  }

                                  public class MyFooCollection : SimpleCollection
                                  {
                                  internal MyFooCollection(IEnumerable myFoos)
                                  : base(myFoos)
                                  { }
                                  }

                                  public class MyBarCollection : SimpleCollection
                                  {
                                  internal MyBarCollection(IEnumerable myBars)
                                  : base(myBars)
                                  { }
                                  }

                                  // In my real code this is a singleton so there will only ever be one pool
                                  public class MyFooMyBarPool
                                  {
                                  private MyFooCollection myFooCollection;
                                  private MyBarCollection myBarCollection;

                                  public MyFooMyBarPool()
                                  {
                                      // Items and collections are instanciated here only.
                                      myFooCollection = new MyFooCollection(new MyFoo\[\] { new MyFoo("A"), new MyFoo("B"), new MyFoo("C") });
                                      myBarCollection = new MyBarCollection(new MyBar\[\] { new MyBar("A"), new MyBar("B"), new MyBar("C") });
                                  }
                                  
                                  public IEnumerable MyBases
                                  {
                                      get
                                      {
                                          IEnumerator myFooEnumer
                                  
                                  L Offline
                                  L Offline
                                  Luc Pattyn
                                  wrote on last edited by
                                  #16

                                  DaveyM69 wrote:

                                  How about getting the enumerator

                                  It seems you're still looking at it in the wrong way, when implemented properly there isn't just one enumerator to a collection, there are as many as you want (and that is why they need storage space outside the collection, hence a new action somewhere). GetEnumerator returns an enumerator, not the enumerator. :)

                                  Luc Pattyn [My Articles] Nil Volentibus Arduum

                                  1 Reply Last reply
                                  0
                                  • D DaveyM69

                                    How about getting the enumerator of each collection to enumerate both of them? I have knocked up an example of the general outline of my classes, I have used this in the MyFooMyBarPool.MyBases property.

                                    using System;
                                    using System.Collections;
                                    using System.Collections.Generic;

                                    public enum BaseType
                                    {
                                    MyFoo,
                                    MyBar
                                    }

                                    public abstract class MyBase
                                    {
                                    private BaseType baseType;
                                    private string name;

                                    internal MyBase(BaseType baseType, string name)
                                    {
                                        this.baseType = baseType;
                                        this.name = name;
                                    }
                                    
                                    public string Name
                                    {
                                        get { return name; }
                                    }
                                    
                                    public override string ToString()
                                    {
                                        return string.Format("Type: {0}, Name: {1}", baseType, name);
                                    }
                                    

                                    }

                                    public sealed class MyFoo : MyBase
                                    {
                                    internal MyFoo(string name)
                                    : base(BaseType.MyFoo, name)
                                    { }
                                    }

                                    public sealed class MyBar : MyBase
                                    {
                                    internal MyBar(string name)
                                    : base(BaseType.MyBar, name)
                                    { }
                                    }

                                    public class SimpleCollection : IEnumerable
                                    {
                                    private List innerList;

                                    public SimpleCollection(IEnumerable items)
                                    {
                                        innerList = new List(items);
                                    }
                                    
                                    public T this\[int index\]
                                    {
                                        get { return innerList\[index\]; }
                                    }
                                    public int Count
                                    {
                                        get { return innerList.Count; }
                                    }
                                    
                                    public IEnumerator GetEnumerator()
                                    {
                                        return innerList.GetEnumerator();
                                    }
                                    IEnumerator IEnumerable.GetEnumerator()
                                    {
                                        return innerList.GetEnumerator();
                                    }
                                    

                                    }

                                    public class MyFooCollection : SimpleCollection
                                    {
                                    internal MyFooCollection(IEnumerable myFoos)
                                    : base(myFoos)
                                    { }
                                    }

                                    public class MyBarCollection : SimpleCollection
                                    {
                                    internal MyBarCollection(IEnumerable myBars)
                                    : base(myBars)
                                    { }
                                    }

                                    // In my real code this is a singleton so there will only ever be one pool
                                    public class MyFooMyBarPool
                                    {
                                    private MyFooCollection myFooCollection;
                                    private MyBarCollection myBarCollection;

                                    public MyFooMyBarPool()
                                    {
                                        // Items and collections are instanciated here only.
                                        myFooCollection = new MyFooCollection(new MyFoo\[\] { new MyFoo("A"), new MyFoo("B"), new MyFoo("C") });
                                        myBarCollection = new MyBarCollection(new MyBar\[\] { new MyBar("A"), new MyBar("B"), new MyBar("C") });
                                    }
                                    
                                    public IEnumerable MyBases
                                    {
                                        get
                                        {
                                            IEnumerator myFooEnumer
                                    
                                    L Offline
                                    L Offline
                                    Luc Pattyn
                                    wrote on last edited by
                                    #17

                                    This is what Reflector gives for List<T> GetEnumerator():

                                    public Enumerator GetEnumerator()
                                    {
                                    return new Enumerator((List<T>) this);
                                    }

                                    Please notice the new keyword. :)

                                    Luc Pattyn [My Articles] Nil Volentibus Arduum

                                    D 1 Reply Last reply
                                    0
                                    • L Luc Pattyn

                                      This is what Reflector gives for List<T> GetEnumerator():

                                      public Enumerator GetEnumerator()
                                      {
                                      return new Enumerator((List<T>) this);
                                      }

                                      Please notice the new keyword. :)

                                      Luc Pattyn [My Articles] Nil Volentibus Arduum

                                      D Offline
                                      D Offline
                                      DaveyM69
                                      wrote on last edited by
                                      #18

                                      So when I call myFooCollection.GetEnumerator(); which in turn calls innerList.GetEnumerator(); where innerList is a List<T> I am actually getting a new enumertor anyway, and the same for myBarCollection.GetEnumerator();, therefore there is no problem with:

                                      IEnumerator myFooEnumerator = myFooCollection.GetEnumerator();
                                      while (myFooEnumerator.MoveNext())
                                      yield return myFooEnumerator.Current;
                                      IEnumerator myBarEnumerator = myBarCollection.GetEnumerator();
                                      while (myBarEnumerator.MoveNext())
                                      yield return myBarEnumerator.Current;

                                      as a new enumerator for the collections is created everytime?

                                      Dave
                                      Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
                                      BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

                                      L 1 Reply Last reply
                                      0
                                      • D DaveyM69

                                        So when I call myFooCollection.GetEnumerator(); which in turn calls innerList.GetEnumerator(); where innerList is a List<T> I am actually getting a new enumertor anyway, and the same for myBarCollection.GetEnumerator();, therefore there is no problem with:

                                        IEnumerator myFooEnumerator = myFooCollection.GetEnumerator();
                                        while (myFooEnumerator.MoveNext())
                                        yield return myFooEnumerator.Current;
                                        IEnumerator myBarEnumerator = myBarCollection.GetEnumerator();
                                        while (myBarEnumerator.MoveNext())
                                        yield return myBarEnumerator.Current;

                                        as a new enumerator for the collections is created everytime?

                                        Dave
                                        Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
                                        BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

                                        L Offline
                                        L Offline
                                        Luc Pattyn
                                        wrote on last edited by
                                        #19

                                        That seems correct. And the unit test I suggested earlier confirms it. :)

                                        Luc Pattyn [My Articles] Nil Volentibus Arduum

                                        1 Reply Last reply
                                        0
                                        Reply
                                        • Reply as topic
                                        Log in to reply
                                        • Oldest to Newest
                                        • Newest to Oldest
                                        • Most Votes


                                        • Login

                                        • Don't have an account? Register

                                        • Login or register to search.
                                        • First post
                                          Last post
                                        0
                                        • Categories
                                        • Recent
                                        • Tags
                                        • Popular
                                        • World
                                        • Users
                                        • Groups