Sign in to follow this  
BrickInTheWall

Have some questions about custom collections in C#

Recommended Posts

Hi, I'm having a difficult time understanding how collections really work. Everything is totally obscured for me because of all the interfaces etc. being used etc. Right now my main concern are the abstract base classes CollectionBase and DictionaryBase you can inherit from. For example a simple class like this:
    public class Animals : CollectionsBase
    {
        public void Add(Animal newAnimal)
        {
            List.Add(newAnimal);
        }

        public void Remove(Animal newAnimal)
        {
            List.Remove(newAnimal);
        }

        public Animals()
        {
        }
    }
What is this "List"? I've looked through some stuff on MSDN and it seems like an automatic property to me but I really don't know. It must have a return type to some type of Class or something if you can use methods like List.Add() etc. Can anyone explain to me how this works, what interfaces and classes come into play here, or just give me a good tutorial on the entire thing? Cheers, Chris

Share this post


Link to post
Share on other sites
You can always look at the exact signature of those classes/units:

using System;
using System.Runtime.InteropServices;

namespace System.Collections {
public abstract class CollectionBase : IList, ICollection, IEnumerable {

protected CollectionBase ();
protected CollectionBase (int capacity);
public int Capacity { get; set; }
public int Count { get; }
protected ArrayList InnerList { get; }
protected IList List { get; }
public void Clear ();
public IEnumerator GetEnumerator ();
protected virtual void OnClear ();
protected virtual void OnClearComplete ();
protected virtual void OnInsert (int index, object value);
protected virtual void OnInsertComplete (int index, object value);
protected virtual void OnRemove (int index, object value);
protected virtual void OnRemoveComplete (int index, object value);
protected virtual void OnSet (int index, object oldValue, object newValue);
protected virtual void OnSetComplete (int index, object oldValue, object newValue);
protected virtual void OnValidate (object value);
public void RemoveAt (int index);
}
}


As you see, it derives from IList, and indeed has a member List, and its return type is IList. CollectionBase itself is abstract, and hence does not need to implement IList, but non-abstract derivations of CollectionBase shall.

Tbh, I am not sure why that List member is needed.

Share this post


Link to post
Share on other sites
Thanks, sorry for the noobish question, but where can I look at that code?
Also, since I now know List's type, I kinda tried creating something similar myself.

I've created my own interface which is supposed to be like IList:

public interface CollectionInterface
{
void Add(Object newObject);
int GetLength();
}


and implemented it in an abstract class which acts kind of like CollectionBase:


public abstract class CollectionBaseClass : CollectionInterface
{
// public for viewing purposes
protected Object[] theArray = new Object[0];

public void Add(Object newObject)
{
int newLength = theArray.Length + 1;
Object[] tempArray = new Object[newLength - 1];
theArray.CopyTo(tempArray, 0);
theArray = new Object[newLength];
theArray[newLength - 1] = newObject;
tempArray.CopyTo(theArray, 0);
}

public int GetLength()
{
return theArray.Length;
}

public CollectionInterface MyList
{
get
{
return this;
}
}
}

I read somewhere on MSDN that List (here MyList) returns an instance to your object...so I tried that...and here is my "custom" collection class which inherets CollectionBaseClass:


public class CollectionClass : CollectionBaseClass
{
public void Add(Animal newAnimal)
{
MyList.Add(newAnimal);
}

public CollectionClass()
{
}

public Animal this[int animalIndex]
{
get
{
return (Animal)theArray[animalIndex];
}
}

public IEnumerator GetEnumerator()
{
for (int i = 0; i < theArray.Length; i++)
{
yield return (Animal)theArray[i];
}
}
}


My main code works...I implemented GetEnumerator so I can use my fake Collection in a foreach loop:
(My main program)

static void Main(string[] args)
{
CollectionClass myNewCollection = new CollectionClass();
Animal myAnimal = new Animal("Rover");
myNewCollection.Add(myAnimal);
myNewCollection.Add(new Animal("Lassy"));

Console.WriteLine(myNewCollection.GetLength());
Console.WriteLine(myNewCollection[0].Name);
Console.WriteLine(myNewCollection[1].Name);

foreach (Animal i in myNewCollection)
{
Console.WriteLine(i.Name);
}

Console.ReadKey();
}

It all works fine...I haven't quite gotten how it really works though using IList and CollectionBase, since in a class that inherets both of these (so basically my custom collection) you add the indexer like this:


public Animal this[int animalIndex]
{
get
{
return (Animal)List[animalIndex];
}
}


I however have to access the array that I'm using to store the objects whereas they can use an index with the List property...I tried using an indexer with the List property, but I couldn't get it to work. Can someone tell me how this could be accomplished? Also, where exactly are IList's Add() and Remove() methods (those for example) implemented? I just kinda put them where it fits best for me. I could be way off with my code as to how it actually works, but heck, I tried.

Thanks,
Chris

Share this post


Link to post
Share on other sites
The recommended method for custom collections in .NET 2.0 and above is to derive your type from System.Collections.ObjectModel.Collection<T> for normal collections and from System.Collections.ObjectMode.ReadOnlyCollection<T> for read-only collections.

You can override the provided InsertItem, SetItem, RemoveItem, and ClearItems methods for custom logic during these operations.

Share this post


Link to post
Share on other sites
aight thanks guys, I took a good look at CollectionBase.cs, the interfaces and the ArrayList.cs file (holy crap) and understand the principles of how its built up. My code has the same idea except it's complete crap compared to the files you use to make custom collections.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this