Results 1 to 13 of 13

Thread: Custom Generic List

  1. #1

    Thread Starter
    PowerPoster motil's Avatar
    Join Date
    Apr 2009
    Location
    Tel Aviv, Israel
    Posts
    2,143

    Custom Generic List

    Hi all!

    I tried to create my first custom list which implement the IList and IEnumerable
    interfaces the code is kinda long but if someone will be kind enough to quickly view it and give me some pointers if i took the wrong path along the way, and i guess if someone will want to learn it itself it could be good starting point so no hard to post the code anyway, well here it is:
    Code:
    class XList<T> : IList<T>
        {
            private List<T> internalList = new List<T>();
            public XList() {}
            private int _Index =0;
            public int Index
            {
                get { return _Index; }
            }
    
            #region Filtering
            public void Remove(Predicate<T> filter)
            {
                for (int i = internalList.Count-1;i>0; i--)
                {
                    if (filter(internalList[i]))
                    {
                        internalList.Remove(internalList[i]);
                    }
                }
            }
            #endregion
    
            #region Sorting methods
            public void Sort()
            {
                internalList.Sort();
            }
    
            public void Sort(IComparer<T> compartion)
            {
                internalList.Sort(compartion);
            } 
            #endregion
    
            #region Rotators
    
            /// <summary>
            /// noraml foreach loop but with the ability to get index
            /// use XList[T].Index to get the current index
            /// </summary>
            /// <returns>IEnumerable[T]</returns>
            public IEnumerable<T> WithIndex()
            {
                for(_Index = 0;_Index < internalList.Count;_Index++)
                {
                    yield return internalList[_Index];
                }
            }
            #endregion
    
            #region IList<T> methods implements
    
            public int IndexOf(T item)
            {
                return internalList.IndexOf(item);
            }
    
            public void Insert(int index, T item)
            {
                internalList.Insert(index, item);
            }
    
            public void RemoveAt(int index)
            {
                internalList.RemoveAt(index);
            }
    
            public T this[int index]
            {
                get
                {
                    return internalList[index];
                }
                set
                {
                    internalList[index] = value;
                }
            }
    
            public void Add(T item)
            {
                internalList.Add(item);
            }
    
            public void Clear()
            {
                internalList.Clear();
            }
    
            public bool Contains(T item)
            {
               return  internalList.Contains(item);
            }
    
            #region CopyTo overloads
    
            /// <summary>
            /// Copy XList into Array[T]
            /// </summary>
            /// <param name="array">Array[T]</param>
            /// <param name="arrayIndex">Start Index</param>
            public void CopyTo(T[] array, int arrayIndex)
            {
                internalList.CopyTo(array, arrayIndex);
            }
    
            /// <summary>
            /// Copy XList[T] into List[T]
            /// </summary>
            /// <param name="array">List[T]</param>
            /// <param name="arrayIndex">Start index</param>
            public void CopyTo(List<T> array, int arrayIndex)
            {
                foreach (var item in internalList)
                {
                    array.Add(item);
                }
            }
    
    
    
    
            /// <summary>
            /// Copy XList[T] into XList[T]
            /// </summary>
            /// <param name="array">XList[T]</param>
            /// <param name="arrayIndex">Start index</param>
            public void CopyTo(XList<T> array, int arrayIndex)
            {
                for(int i=0;i< array.Count;i++)
                {
                    array.Add(array[i]);
                }
            } 
    
            #endregion
    
            public int Count
            {
                get { return internalList.Count; }
            }
    
            public bool IsReadOnly
            {
                get { throw new NotImplementedException(); }
            }
    
            public bool Remove(T item)
            {
               return internalList.Remove(item);
            }
    
            public IEnumerator<T> GetEnumerator()
            {
                return new XListEnumerator<T>(internalList);
            }
    
            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                return internalList.GetEnumerator();
    
            } 
            #endregion
    
        }
    
    
        #region XList Enumerator class
        public class XListEnumerator<T> :IEnumerator<T>
        {
            private List<T> internalList = new List<T>();
            private int _index = -1;
           
    
            #region Constructors
            public XListEnumerator(List<T> l)
            {
                internalList = l;
            }
            #endregion
    
    
            #region Methods
            
            #endregion
    
            #region IEnumerator Implements methods
            public object Current
            {
                get { return internalList[_index]; }
            }
    
            public bool MoveNext()
            {
                return ++_index < internalList.Count;
            }
    
            public void Reset()
            {
                _index = -1;
            } 
            #endregion
    
            T IEnumerator<T>.Current
            {
                get { return internalList[_index]; }
            }
    
            public void Dispose()
            {
                internalList = null;
            }
    
           
        }
    Last edited by motil; Oct 30th, 2010 at 09:06 AM.
    * Rate It If you Like it

    __________________________________________________________________________________________

    "Programming is like sex: one mistake and you’re providing support for a lifetime."

    Get last SQL insert ID

  2. #2
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,222

    Re: Custom Generic List

    It's a rare thing that you would actually implement IList yourself. Normally, you'd simply inherit System.Collections.ObjectModel.Collection<T> and then add the extra functionality you needed to that. You get a lot for free that way. If you really want to provide your own implementation then isn't it rather cheating to use a List<T> internally?
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  3. #3

    Thread Starter
    PowerPoster motil's Avatar
    Join Date
    Apr 2009
    Location
    Tel Aviv, Israel
    Posts
    2,143

    Re: Custom Generic List

    Hi jm, I just started to learn the subject of generic types so basically i'm currently playing with it, but for now i do prefer to implement interfaces by hand (as i did with the XListEnumerator<T> :IEnumerator<T> at the bottom) which i didn't have to, i do that because as i said i'm currently learning.

    any other pointers ?
    * Rate It If you Like it

    __________________________________________________________________________________________

    "Programming is like sex: one mistake and you’re providing support for a lifetime."

    Get last SQL insert ID

  4. #4

    Thread Starter
    PowerPoster motil's Avatar
    Join Date
    Apr 2009
    Location
    Tel Aviv, Israel
    Posts
    2,143

    Re: Custom Generic List

    JM, when i inherit from Collection<T> like so:
    Code:
    class XList<T> : Collection<T>
        {
            ....
        }
    can i rotate through the collection items some how like i did in my first example ?
    * Rate It If you Like it

    __________________________________________________________________________________________

    "Programming is like sex: one mistake and you’re providing support for a lifetime."

    Get last SQL insert ID

  5. #5
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,687

    Re: Custom Generic List

    The point of inheriting is so that you don't have to reinvent the wheel... you automatically gain that functionality built into the base class... so the answer is, yes. And you don't have to write any code to do it.

    In your first example, you implemented IList... but then had an internal list object... so what was the point? All you actually did was create a wrapper class, and are simply passing the methods through. It just adds a layer of complexity that isn't necessary and doesn't add any value.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  6. #6

    Thread Starter
    PowerPoster motil's Avatar
    Join Date
    Apr 2009
    Location
    Tel Aviv, Israel
    Posts
    2,143

    Re: Custom Generic List

    take it easy guys
    i'm new to this subject, teaching myself (never took a single course in programing) and only have 1 year + few months working with .NET and OOP programing and i spent most of this time working with ASP.NET
    (which require less understanding of complex C#/VB.NET) , I'm trying to improve my skill and getting to higher levels and I will get there (I hope)

    i would really appreciate constructive criticism instead of "you're sooo wrong" comments, this is the reason i posted the code. you're both MVP's so and I really look up to you both so please understand that i just trying to learn.

    anyhow if i'll have more question i'll post it here, i'll just make sure to put my bullet-proof vest before posting

    thanks for the info guys.
    Last edited by motil; Oct 30th, 2010 at 12:47 PM.
    * Rate It If you Like it

    __________________________________________________________________________________________

    "Programming is like sex: one mistake and you’re providing support for a lifetime."

    Get last SQL insert ID

  7. #7
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,687

    Re: Custom Generic List

    That IS what we're trying to show you... you "implemented" an interface, then treated the class as a simple wrapper... again, that just adds a layer of complexity that was unnecessary. The generally accepted process is to INHERIT from the collections class, then simply just add your custom code. the rest, add, remove, copy, insertat, etc, is all done for you... you don't need to maintain an internal list, because your class IS the list... That's usually the hardest part of the custom list class to get over... the class IS THE LIST... and as such, you don't need to maintain an internal list.

    Consider this ( I used List<> rather than Collection<> though):
    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ClassLibrary1
    {
        public class Class1
        {
            XList<Int32> myList = new XList<int>();
            void sub1() {
                myList.Add (1);
                myList.Add (2);
                myList.Add (3);
                myList.Add (4);
                myList.Add (5);
    
                foreach(Int32 myInt in myList ) {
                    System.Diagnostics.Debug.WriteLine(myInt.ToString );
                }
                myList.RemoveAt(2); //remove #3
    
                foreach (Int32 myInt in myList)
                {
                    System.Diagnostics.Debug.WriteLine(myInt.ToString);
                }
    
                myList.Clear();
                System.Diagnostics.Debug.WriteLine(myList.Count.ToString ():
            }
        }
    
        public class XList<T> : List<T>
        {
    
        }
    }
    As you can see, I didn't add any code for the Add, RemoveAt or the Clear... but it all works... because the base class that I inherited from implements that functionality already. Now, if I wanted to do something additional when an item is added, then the Add method could be overriden and the new functionality added. And there's no internal list either. And that's the point jmc was trying to make... sometimes people need to be thumped on the head... as for the feeling that we came down too hard on you ... what are we supposed to do? Pat you on the head and say "that's nice"? No... if it's wrong, it's wrong... we tried to correct that by pointing out that you shouldn't have to implement the ilist interface when it's already done for you... now... if you don't want to hear that... then there's not much else we can do to help.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  8. #8

    Thread Starter
    PowerPoster motil's Avatar
    Join Date
    Apr 2009
    Location
    Tel Aviv, Israel
    Posts
    2,143

    Re: Custom Generic List

    There is no need for patting here, just good explanations and some direction to the correct path, it's easy to get to the wrong truck in the huge world of this .NET framework .

    I already understood that the way to go is to inherit from the Collection class as jm wrote in his first comment and that's what i did, but my question is, if for example i want to add the ability for my custom list to rotate in reverse, or to return the index of the current item when using the foreach statement, do i have any access to the list of items from within the class ?
    * Rate It If you Like it

    __________________________________________________________________________________________

    "Programming is like sex: one mistake and you’re providing support for a lifetime."

    Get last SQL insert ID

  9. #9

    Thread Starter
    PowerPoster motil's Avatar
    Join Date
    Apr 2009
    Location
    Tel Aviv, Israel
    Posts
    2,143

    Re: Custom Generic List

    Ok, i think i have the answer, i can loop on this with something like this:

    Code:
    class XList<T> : Collection<T>
        {
    
            public void test()
            {
                for (int i = 0; i < this.Count; i++)
                {
                    Console.WriteLine(this[i]);
                }
            }
        }
    is it correct ?
    Last edited by motil; Oct 30th, 2010 at 03:42 PM.
    * Rate It If you Like it

    __________________________________________________________________________________________

    "Programming is like sex: one mistake and you’re providing support for a lifetime."

    Get last SQL insert ID

  10. #10
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,222

    Re: Custom Generic List

    There are two options for accessing the items internally. You certainly can use 'this' because, like tg says, the class IS the list. That said, if you read the documentation for the Collection<T> class, you'll see that there's an Items property, which provides an IList by which you can access the items. The main difference is that using Items bypasses the overridable members of the Collection<T> class that you are intended to use to provide custom functionality.

    Why would that be advantageous? For one thing, it would allow you to filter and sort without invoking the functionality you've added to those methods. Consider a collection where you have overridden the InsertItem method to pre-process items that are added to the list. Now let's say that you add a Sort method. To sort the items, you'll need to move them, which will involve adding them to the list in a different position. If you use 'this' then you'll invoke the InsertItem method each time, which you don't really want because all the items have already been processed. Using the Items property allows you to add the items in a different order without invoking InsertItem.

    By the way, you seem to be taking things a bit personally. I went back and re-read posts #2 and #5 and there's nothing there that warrants requests to "take it easy'. You want a critique of your approach and we're giving you one. We can't really try to help you improve your original IList implementation because it's simply not a situation where a direct IList implementation is warranted.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  11. #11

    Thread Starter
    PowerPoster motil's Avatar
    Join Date
    Apr 2009
    Location
    Tel Aviv, Israel
    Posts
    2,143

    Re: Custom Generic List

    yea i already found out about the Items property when i needed to use the .Sort() method which you can't call it directly from the Collection object but instead you must Cast the Items Property of the Collection to List.

    but there is something that is a bit in the fog for me, up until now, when the keyword this meant an instance of the class for me.

    and now with the collection example i use it as a collection of items or array of instances, which I never faced this behavior before. it's nice that its working but i also like to understand why is it working.

    i read earlier that the Collection<T> class is just a wrapper of an object the implements the IList interfaces and the IList actually wrap a List ? is that true ? is there list object somewhere in the background or did i get it wrong again?

    one more thing, when you saying read the documentation did you mean this: http://msdn.microsoft.com/en-us/library/ms132397.aspx

    if not please direct me to the right location.

    finally:
    about me taking it things personally, I'm sorry if I got you guys wrong, the thing is that i didn't even tried to create real efficient custom List i was just playing with what i've learn from the book (which is very good) i'm reading and it was about implementing interfaces and also about generic types

    anyway thanks again for the help.
    * Rate It If you Like it

    __________________________________________________________________________________________

    "Programming is like sex: one mistake and you’re providing support for a lifetime."

    Get last SQL insert ID

  12. #12
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,222

    Re: Custom Generic List

    The keyword 'this' refers to the current instance of the current class. If you use 'this' inside your XList<T> class then you're referring to the current XList object. It works exactly the same way no matter what. Your collection is still an object. Is an egg carton any less an object than an egg?
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  13. #13

    Thread Starter
    PowerPoster motil's Avatar
    Join Date
    Apr 2009
    Location
    Tel Aviv, Israel
    Posts
    2,143

    Re: Custom Generic List

    so my XList object -> Collection Object are both actually a list of object? at the end of the line what exactly are this list made of ?
    * Rate It If you Like it

    __________________________________________________________________________________________

    "Programming is like sex: one mistake and you’re providing support for a lifetime."

    Get last SQL insert ID

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width