|
-
Oct 30th, 2010, 09:03 AM
#1
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 
-
Oct 30th, 2010, 09:09 AM
#2
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?
-
Oct 30th, 2010, 09:14 AM
#3
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 
-
Oct 30th, 2010, 11:40 AM
#4
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 
-
Oct 30th, 2010, 12:27 PM
#5
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
-
Oct 30th, 2010, 12:40 PM
#6
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 
-
Oct 30th, 2010, 02:53 PM
#7
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
-
Oct 30th, 2010, 03:20 PM
#8
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 
-
Oct 30th, 2010, 03:38 PM
#9
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 
-
Oct 30th, 2010, 06:20 PM
#10
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.
-
Oct 30th, 2010, 07:40 PM
#11
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 
-
Oct 30th, 2010, 08:14 PM
#12
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?
-
Oct 31st, 2010, 03:25 AM
#13
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|