Saturday, November 12, 2011

Two ways to extend Collection class

Collection class definitely missing the pretty useful method of the List class such as Find, ForEach, AddRange, etc.., We can arm the collection class with these implementation in two ways. One is to use the extension methods technology and another way is to use the underlying implementation of List class of the Collection. Here they are...

Extension method
------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public static class CollectionExtensions
{
    public static void AddRange(this Collection collection, IEnumerable values)
    {
        foreach (var item in values)
        {
            collection.Add(item);
        }
    }

    public static T Find(this Collection collection, Predicate predicate)
    {
        foreach (var item in collection)
        {
            if (predicate(item))
                return item;
        }
        return default(T);
    }

    public static Collection FindAll(this Collection collection, Predicate predicate)
    {
        Collection all = new Collection();
        foreach (var item in collection)
        {
            if (predicate(item))
                all.Add(item);
        }
        return all;
    }

    public static int FindIndex(this Collection collection, Predicate predicate)
    {
        return FindIndex(collection, 0, predicate);
    }

    public static int FindIndex(this Collection collection, int startIndex, Predicate predicate)
    {
        return FindIndex(collection, startIndex, collection.Count, predicate);
    }

    public static int FindIndex(this Collection collection, int startIndex, int count, Predicate predicate)
    {
        for (int i = startIndex; i < count; i++)
        {
            if (predicate(collection[i]))
                return i;
        }
        return -1;
    }

    public static T FindLast(this Collection collection, Predicate predicate)
    {
        for (int i = collection.Count - 1; i >= 0; i--)
        {
            if (predicate(collection[i]))
                return collection[i];
        }
        return default(T);
    }

    public static int FindLastIndex(this Collection collection, Predicate predicate)
    {
        return FindLastIndex(collection, collection.Count - 1, predicate);
    }

    public static int FindLastIndex(this Collection collection, int startIndex, Predicate predicate)
    {
        return FindLastIndex(collection, startIndex, startIndex + 1, predicate);

    }

    public static int FindLastIndex(this Collection collection, int startIndex, int count, Predicate predicate)
    {
        for (int i = startIndex; i >= startIndex - count; i--)
        {
            if (predicate(collection[i]))
                return i;
        }
        return -1;
    }

    public static void ForEach(this Collection collection, Action action)
    {
        foreach (var item in collection)
        {
            action(item);
        }
    }

    public static int RemoveAll(this Collection collection, Predicate match)
    {
        int count = 0;
        for (int i = 0; i < collection.Count; i++)
        {
            if (match(collection[i]))
            {
                collection.Remove(collection[i]);
                count++;
                i--;
            }
        }
        return count;
    }

    public static bool TrueForAll(this Collection collection, Predicate match)
    {
        foreach (var item in collection)
        {
            if (!match(item))
                return false;
        }
        return true;
    }
} 
Using underlying List class
---------------------------
public class ListCollection : Collection
where T : class
  {
// A default constructor 
  public ListCollection() : base(new List()) { } 

    // A "converter" constructor, which does not copy the list passed in.
    // See http://msdn.microsoft.com/en-us/library/ms132401.aspx 
    public ListCollection(IList list) : base(list) { }
 
    public void AddRange(IEnumerable values)
{
((List)this.Items).AddRange(values);
}
 
    public bool Exists(Predicate match)
{
return ((List)this.Items).Exists(match);
}
 
    public T Find(Predicate match) 
{
return ((List)Items).Find(match);
}
 
    public ListCollection FindAll(Predicate match) 
{
      return new ListCollection(((List)Items).FindAll(match));
    }
 
    public int FindIndex(Predicate match)
{
return ((List)Items).FindIndex(match);
}
 
    public int FindIndex(int startIndex, Predicate match) 
{
return ((List)Items).FindIndex(startIndex, match);
}
 
    public int FindIndex(int startIndex, int count, Predicate match)
{
return ((List)Items).FindIndex(startIndex, count, match);
}
 
    public T FindLast(Predicate match)
{
return ((List)Items).FindLast(match);
}
 
    public int FindLastIndex(Predicate match) 
{
return ((List)Items).FindLastIndex(match);
}
 
    public int FindLastIndex(int startIndex, Predicate match) 
{
return ((List)Items).FindLastIndex(startIndex, match);
}
 
    public int FindLastIndex(int startIndex, int count, Predicate match)
{
return ((List)Items).FindLastIndex(startIndex, count, match);
}
 
    public void ForEach(Action action) 
{
((List)Items).ForEach(action);
}
 
    public int RemoveAll(Predicate match) 
{
return ((List)Items).RemoveAll(match);
}
 
    public bool TrueForAll(Predicate match) 
{
return ((List)Items).TrueForAll(match);
}