- ArrayList : Dynamic size collection of objects listed in sequential order.
- Hashtable : Collection of key/value pairs that are organized based on the hash code of the key.
- Queue : FIFO collection.
- SortedList : Collection of key/value pairs that sorted by the keys and are accessible by key and by index.
- Stack : LIFO collection.
- ICollection : General Characteristic such as; size, enumeration, and thread safety.
- ICloneable : Return a copy of itself
- IDictionary : Represent it contents using key/value pairs.
- IEnumerable : Retrun object implemented IEnumerator.
- IList : Provides add, remove, and index item in a sequential list of objects,
BitVector32, ListDictionary, StringDictionary, StringCollection.
Issue With Non_Generics Collections:
- poor performance since CLR needs to perform number of memory transfer operations when you store structures in a classic collection classes.
- not type safe since they were developed to operate on System.Objects.
//ValueType
int ValueTypeInt = 30;
//Box int into the object reference
object boxedInt = ValueTypeInt;
//Unbox the reference back into the corresponding int.
int UnboxedInt = (int)boxedInt;
You need to place the unbox block in try/catch since it might cause an exception if you are not expecting correct underling value.
Any non_generic type built to operate on objects, represent data allocated on the heap. Runtime automatically boxes the stack-based data on your behalf, and you need to unbox it when you want to retrieve an item. Boxing and unboxing cause performance issues.
Type Safety Issue:
Type safety insure C# compiler determine any attempt to insert an incompatible data type.Custom collections (strongly typed) can provide type safety, however the problem is that you need to create an almost identical custom collection for each unique data type you wish to contain. Consider the following example:
public class ShapeCollection : IEnumerable
{
//declare a private ArrayList
private ArrayList shape_array = new ArrayList();
public Shape GetShape(int pos)
{
return (Shape)shape_array[pos];
}
//Only accept Shape type
public void AddShape(Shape s)
{
shape_array.Add(s);
}
public void ClearShape()
{
shape_array.Clear();
}
public int Count
{
get { return shape_array.Count; }
}
public IEnumerator GetEnumerator()
{
return shape_array.GetEnumerator();
}
}
There is no way to get rid of boxing and unboxing using non-generic custom collection classes. System.Collection.Generic namespace contain generic types such as List<> generic type which help you to obtain type safe and escape from boxing/unboxing penalties.
Generics:
You can write classes, structures, interfaces, and delegates generically but not enum types.
Object browser (System.Collections.Generic) |
- T is used for types
- TKey or K is used for keys
- TValue or V is used for values.
Generic member example:
int[] numbers = {100, 50, 2, 30, 70, 5};
//Type parameter for Generic Members
Array.Sort<int>(numbers);
Generic Interfaces:
It is always better if you choose to use generic interfaces in case of availability to avoid runtime checks and casting operations. IComparable generic interface is look like this:
public interface IComparable<in T>
{
int CompareTo(T other);
}
Implementation of this interface is goes as follow:
class Shape:IComparable<Shape>
{
//Explicit implementation
int IComparable<Shape>.CompareTo(Shape other)
{
if (this.ShapeID > other.ShapeID)
return 1;
else if (this.ShapeID < other.ShapeID)
return -1;
else
return 0;
}
}
For more information about generic collection you can refer to System.Collections.Generic Namespace at MSDN. SortedSet<T> :
A generic class introduced in .NET 4.0 which automatically sort the items. You need to send an object which implement the IComparer<T> as a constructor argument to specify the criteria for sorting. Consider the following example:
//sort by ShapeID
class SortShpaesByID : IComparer<Shape>
{
public int Compare(Shape first_shape, Shape second_shape)
{
if (first_shape.ShapeID > second_shape.ShapeID)
return 1;
else if (first_shape.ShapeID < second_shape.ShapeID)
return -1;
else
return 0;
}
}
You may use the above generic class like this:
static void Main(string[] args)
{
//create a SortedSet
SortedSet<Shape> sortedShapes = new SortedSet<Shape>(new SortShpaesByID());
}
When your overloaded methods just differ by incoming arguments, you may use generics. Example:
static void Swap<T>(ref T first, ref T second)
{
T temp = first;
first = second;
second = temp;
}
You can use the above generic like this:
int int_1 = 3;
int int_2 = 60;
Swap<int>(ref int_1, ref int_2);
You can optionally remove the type parameter if and only if the generic method requires arguments.
In order to set the default value for generic you can use default keyword just like the following example:
T temp = first;
first = default(T);
Generics classes can be the base class and derived class need to follow these rules:- Derived class must specify a type parameter when a non-generic class extends a generic class.
- Derived type must override the generic methods using the specified type parameter, when generic base class defines generic virtual or abstract methods.
- The child class can (optionally) reuse the type placeholder in its definition, when the derived type is generic as well.
With help of where keyword you can get extremely specific about what a given type parameter must look like:
- where T : struct (T must be a structure, "must have System.ValueTyep")
- where T : class (T must be reference type)
- where T : new() (T must have default constructor)
- where T : NameOfBaseClass (T must be derived from the class specified by name of baseClass)
- where T : NameOfInterface (T must implement the interface specified by NameOfInterface)
public class Calculate<T> where T: operator +, operator -, operator *, operator /
{
public T Add (T first, T second)
{
return first + second;
}
.
.
.
}
Reference: Pro C# 2010 and the .NET 4 Platform by Andrew Troelsen.
No comments:
Post a Comment