There are five types of constraints:

   
 
/*
    *Derivation constraints state the ascendancy of a type parameter.
    *Interface constraints are interfaces that are implemented by the type parameter.
    *Value type constraints restrict a type parameter to a value type.
    *Reference type constraints restrict a type parameter to a reference type.
    *Constructor constraints stipulate that the type parameter has a default or parameterless constructor.
*/

    


Represents a generic collection of key/value pairs. The enumerator returns the values in the order assigned.

   
 

//http://visualizer.codeplex.com/license
//Microsoft Public License (Ms-PL)

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

namespace Redwerb.BizArk.Core.Collections
{

    /// <summary>
    /// Represents a generic collection of key/value pairs. The enumerator returns the values in the order assigned.
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <typeparam name="TValue"></typeparam>
    public class HashList<TKey, TValue>
        : IList<TValue>
    {

        #region Fields and Properties

        private Dictionary<TKey, int> mDictionary = new Dictionary<TKey, int>();
        private List<TValue> mList = new List<TValue>();

        /// <summary>
        /// Gets or sets the value for the given key.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public TValue this[TKey key]
        {
            get { return GetValue(key); }
            set
            {
                if (mIsReadOnly) throw new InvalidOperationException("The list is readonly.");
                SetValue(key, value);
            }
        }

        /// <summary>
        /// Gets or sets the value at the designated index.
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public TValue this[int index]
        {
            get { return mList[index]; }
            set
            {
                if (mIsReadOnly) throw new InvalidOperationException("The list is readonly.");
                mList[index] = value;
            }
        }

        /// <summary>
        /// Gets the number of items in the list.
        /// </summary>
        public int Count
        {
            get { return mList.Count; }
        }

        private bool mIsReadOnly = false;
        /// <summary>
        /// Gets a value that determines if the list if readonly.
        /// </summary>
        public bool IsReadOnly
        {
            get { return mIsReadOnly; }
            protected set { mIsReadOnly = value; }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Adds the value to the list.
        /// </summary>
        /// <param name="index"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void Insert(int index, TKey key, TValue value)
        {
            if (mIsReadOnly) throw new InvalidOperationException("The list is readonly.");
            if (mDictionary.ContainsKey(key)) throw new ArgumentException("Key already exists in the collection.");

            mList.Insert(index, value);
            foreach (var item in mDictionary.ToArray())
            {
                if (item.Value >= index)
                    mDictionary[item.Key] = item.Value + 1;
            }
            mDictionary.Add(key, index);
        }

        /// <summary>
        /// Adds the value to the list.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void Add(TKey key, TValue value)
        {
            if (mIsReadOnly) throw new InvalidOperationException("The list is readonly.");
            if (mDictionary.ContainsKey(key)) throw new ArgumentException("Key already exists in the collection.");
            SetValue(key, value);
        }

        /// <summary>
        /// Removes the item from the list.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Remove(TKey key)
        {
            if (mIsReadOnly) throw new InvalidOperationException("The list is readonly.");
            if (!mDictionary.ContainsKey(key)) return false;
            var i = mDictionary[key];
            mDictionary.Remove(key);
            mList.RemoveAt(i);
            foreach (var item in mDictionary.ToArray())
            {
                if (item.Value > i)
                    mDictionary[item.Key] = item.Value - 1;
            }
            return true;
        }

        /// <summary>
        /// Removes the item from the list.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool Remove(TValue value)
        {
            if (mIsReadOnly) throw new InvalidOperationException("The list is readonly.");
            var key = GetKey(value);
            return Remove(key);
        }

        /// <summary>
        /// Removes the value at the designated index.
        /// </summary>
        /// <param name="index"></param>
        public void RemoveAt(int index)
        {
            if (mIsReadOnly) throw new InvalidOperationException("The list is readonly.");
            var key = GetKeyFromIndex(index);
            Remove(key);
        }

        /// <summary>
        /// Removes all the items from the list.
        /// </summary>
        public void Clear()
        {
            if (mIsReadOnly) throw new InvalidOperationException("The list is readonly.");
            mDictionary.Clear();
            mList.Clear();
        }

        /// <summary>
        /// Gets the value from the list.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        protected TValue GetValue(TKey key)
        {
            var i = mDictionary[key];
            return mList[i];
        }

        /// <summary>
        /// Gets the value from the list. If the key is not in the list, returns the default value.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="dflt">Default value to return if the key does not exist.</param>
        /// <returns></returns>
        public TValue GetValue(TKey key, TValue dflt)
        {
            TValue value;
            if (TryGetValue(key, out value)) return value;
            return dflt;
        }

        /// <summary>
        /// Gets the value from the list. Returns true if the value exists, otherwise false.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool TryGetValue(TKey key, out TValue value)
        {
            if (!mDictionary.ContainsKey(key))
            {
                value = default(TValue);
                return false;
            }
            var i = mDictionary[key];
            value = mList[i];
            return true;
        }

        /// <summary>
        /// Sets the value in the list.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        protected int SetValue(TKey key, TValue value)
        {
            int i;
            if (mDictionary.ContainsKey(key))
            {
                i = mDictionary[key];
                mList[i] = value;
            }
            else
            {
                mList.Add(value);
                i = mList.Count - 1;
                mDictionary.Add(key, i);
            }
            return i;
        }

        /// <summary>
        /// Determines if the key is in the list.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool ContainsKey(TKey key)
        {
            return mDictionary.ContainsKey(key);
        }

        /// <summary>
        /// Determines if the item is in the list.
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public bool Contains(TValue item)
        {
            return mList.Contains(item);
        }

        /// <summary>
        /// Gets the index of the given item.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public int IndexOf(TKey key)
        {
            if (!mDictionary.ContainsKey(key)) return -1;
            return mDictionary[key];
        }

        /// <summary>
        /// Gets the index of the given item.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public int IndexOf(TValue value)
        {
            return mList.IndexOf(value);
        }

        /// <summary>
        /// Gets the key based on the value.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public TKey GetKey(TValue value)
        {
            var i = mList.IndexOf(value);
            if (i < 0) throw new ArgumentException("Value not found in the collection.");
            foreach (var keyVal in mDictionary)
            {
                if (keyVal.Value == i)
                    return keyVal.Key;
            }
            // This should never happen, but just in case.
            throw new InvalidOperationException("The key was not found in the collection.");
        }

        /// <summary>
        /// Gets the key based on the index.
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public TKey GetKeyFromIndex(int index)
        {
            foreach (var item in mDictionary)
                if (item.Value == index) return item.Key;

            throw new ArgumentOutOfRangeException("The index was not found in the dictionary.");
        }

        /// <summary>
        /// Returns the collection of keys.
        /// </summary>
        public ICollection<TKey> Keys
        {
            get { return mDictionary.Keys; }
        }

        /// <summary>
        /// Gets the enumerator for the list.
        /// </summary>
        /// <returns></returns>
        public IEnumerator<TValue> GetEnumerator()
        {
            return mList.GetEnumerator();
        }

        /// <summary>
        /// Gets the enumerator for the list.
        /// </summary>
        /// <returns></returns>
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        /// <summary>
        /// Gets an array of the values.
        /// </summary>
        /// <returns></returns>
        public TValue[] ToArray()
        {
            return mList.ToArray();
        }

        /// <summary>
        /// Copies the values to an array.
        /// </summary>
        /// <param name="array"></param>
        /// <param name="arrayIndex"></param>
        void ICollection<TValue>.CopyTo(TValue[] array, int arrayIndex)
        {
            mList.CopyTo(array, arrayIndex);
        }

        #endregion

        #region Unsupported IList methods

        void IList<TValue>.Insert(int index, TValue item)
        {
            throw new NotSupportedException("Cannot insert values without the key.");
        }

        void ICollection<TValue>.Add(TValue item)
        {
            throw new NotSupportedException("Cannot add values without the key.");
        }

        #endregion

    }
}

   
     


Generic collection class

   
  
using System;
using System.Collections.Generic;

public class Bag<T> {
    private List<T> items = new List<T>();
    public void Add(T item) {
        items.Add(item);
    }
    public T Remove() {
        T item = default(T);
        if (items.Count != 0) {
            Random r = new Random();
            int num = r.Next(0, items.Count);

            item = items[num];
            items.RemoveAt(num);
        }
        return item;
    }
    public T[] RemoveAll() {
        T[] i = items.ToArray();
        items.Clear();
        return i;
    }
}
public class MainClass {
    public static void Main(string[] args) {
        Bag<string> bag = new Bag<string>();

        bag.Add("D");
        bag.Add("B");
        bag.Add("G");
        bag.Add("M");
        bag.Add("N");
        bag.Add("I");

        Console.WriteLine("Item 1 = {0}", bag.Remove());
        Console.WriteLine("Item 2 = {0}", bag.Remove());
        Console.WriteLine("Item 3 = {0}", bag.Remove());
        Console.WriteLine("Item 4 = {0}", bag.Remove());

        string[] s = bag.RemoveAll();
    }
}

   
     


Add object in a hierarchy into a generic Collection

   
  


using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Text;

public class Chicken : Animal {
    public void LayEgg() {
        Console.WriteLine("{0} Animal.", name);
    }

    public Chicken(string newName)
        : base(newName) {
    }
}

public class Cow : Animal {
    public void Milk() {
        Console.WriteLine("{0} cow.", name);
    }

    public Cow(string newName)
        : base(newName) {
    }
}

public abstract class Animal {
    protected string name;

    public string Name {
        get {
            return name;
        }
        set {
            name = value;
        }
    }

    public Animal() {
        name = "animal";
    }

    public Animal(string newName) {
        name = newName;
    }

    public void Feed() {
        Console.WriteLine("{0} is feeding.", name);
    }
}

class Program {
    static void Main(string[] args) {
        Collection<Animal> animalCollection = new Collection<Animal>();
        animalCollection.Add(new Cow("A"));
        animalCollection.Add(new Chicken("B"));
        foreach (Animal myAnimal in animalCollection) {
            myAnimal.Feed();
        }
    }
}

   
     


Sort by Name

   
  

using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;


public class Employee : System.IComparable {
    private int _id;
    private string _name;
    private string _rating;
    private static SortOrder _order;

    public enum SortOrder {
        Ascending = 0,
        Descending = 1
    }

    public Employee(int id, string name)
        : this(id, name, "Other") {
    }

    public Employee(int id, string name, string rating) {
        this._id = id;
        this._name = name;
        this._rating = rating;
    }

    public int Id {
        get { return this._id; }
        set { this._id = value; }
    }

    public string Name {
        get { return this._name; }
        set { this._name = value; }
    }

    public string Rating {
        get { return this._rating; }
        set { this._rating = value; }
    }

    public static SortOrder Order {
        get { return _order; }
        set { _order = value; }
    }

    public override bool Equals(Object obj) {
        bool retVal = false;
        if (obj != null) {
            Employee custObj = (Employee)obj;
            if ((custObj.Id == this.Id) &amp;&amp;
                (custObj.Name.Equals(this.Name) &amp;&amp;
                (custObj.Rating.Equals(this.Rating))))
                retVal = true;
        }
        return retVal;
    }

    public override string ToString() {
        return this._id + ": " + this._name;
    }

    public int CompareTo(Object obj) {
        switch (_order) {
            case SortOrder.Ascending:
                return this.Name.CompareTo(((Employee)obj).Name);
            case SortOrder.Descending:
                return (((Employee)obj).Name).CompareTo(this.Name);
            default:
                return this.Name.CompareTo(((Employee)obj).Name);
        }
    }

}

public class CollectionTest {
    public static void Main() {
        List<Employee> collCustList = new List<Employee>();
        collCustList.Add(new Employee(99, "H", "P"));
        collCustList.Add(new Employee(77, "B", "G"));
        collCustList.Add(new Employee(55, "B", "G"));
        collCustList.Add(new Employee(88, "B", "P"));
        collCustList.Add(new Employee(11, "L", "O"));

        foreach (Employee cust in collCustList)
            Console.Out.WriteLine(cust);

        Employee.Order = Employee.SortOrder.Ascending;
        collCustList.Sort(delegate(Employee cust1, Employee cust2) {
            return Comparer<Employee>.Default.Compare(cust1, cust2);
        });

        foreach (Employee cust in collCustList)
            Console.Out.WriteLine(cust);

        Employee.Order = Employee.SortOrder.Descending;
        collCustList.Sort(delegate(Employee cust1, Employee cust2) {
            return Comparer<Employee>.Default.Compare(cust1, cust2);
        });

        foreach (Employee cust in collCustList)
            Console.Out.WriteLine(cust);
    }
}

   
     


Add Collection Items with IComparable interface implementation

   
  
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;


public class Customer : System.IComparable {
    private int _id;
    private string _name;
    private string _rating;
    private static SortOrder _order;

    public enum SortOrder {
        Ascending = 0,
        Descending = 1
    }

    public Customer(int id, string name)
        : this(id, name, "Other") {
    }

    public Customer(int id, string name, string rating) {
        this._id = id;
        this._name = name;
        this._rating = rating;
    }

    public int Id {
        get { return this._id; }
        set { this._id = value; }
    }

    public string Name {
        get { return this._name; }
        set { this._name = value; }
    }

    public string Rating {
        get { return this._rating; }
        set { this._rating = value; }
    }

    public static SortOrder Order {
        get { return _order; }
        set { _order = value; }
    }

    public override bool Equals(Object obj) {
        bool retVal = false;
        if (obj != null) {
            Customer custObj = (Customer)obj;
            if ((custObj.Id == this.Id) &amp;&amp;
                (custObj.Name.Equals(this.Name) &amp;&amp;
                (custObj.Rating.Equals(this.Rating))))
                retVal = true;
        }
        return retVal;
    }

    public override string ToString() {
        return this._id + ": " + this._name;
    }

    public int CompareTo(Object obj) {
        switch (_order) {
            case SortOrder.Ascending:
                return this.Name.CompareTo(((Customer)obj).Name);
            case SortOrder.Descending:
                return (((Customer)obj).Name).CompareTo(this.Name);
            default:
                return this.Name.CompareTo(((Customer)obj).Name);
        }
    }

}

public class CollectionTest {
    public static void Main() {
        Collection<Customer> custColl = new Collection<Customer>();
        custColl.Add(new Customer(1, "S"));
        custColl.Add(new Customer(2, "K"));
        custColl.Add(new Customer(3, "T"));

        custColl.Insert(1, new Customer(4, "Inserted Employee"));

        custColl[3] = new Customer(9, "F");

        foreach (Customer cust in custColl)
            Console.Out.WriteLine(cust);
    }
}

   
     


Add user-defined object to generic Collection

   
  
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Text;

class Team {
    private string name;

    public Team(string name) {
        this.name = name;
    }

    public override string ToString() {
        return name;
    }
}

class Program {
    static void Main(string[] args) {
        Collection<Team> teams = new Collection<Team>();
        teams.Add(new Team("Ferrari"));
        teams.Add(new Team("Williams-BMW"));
        teams.Add(new Team("Bar-Honda"));
        teams.Add(new Team("McLaren-Mercedes"));

        foreach (Team t in teams) {
            Console.WriteLine(t);
        }
    }
}