serving the solutions day and night

Pages

Friday, September 10, 2010

C# - Generics, Boxing, Unboxing

Generics
- C# is a strongly typpe language, when using C# you should declare a type prior to storing data in it.
- Generics types to eliminate redundant code, type safety, code re-usability and performance.
- create generic interfaces, classes, methods, events and delegates.
- Generic can be defined by putting the <T> sign after the class or method name. instead of "T" you can use any word.
- Generic data type obtained at run-time by using reflection.
- Generics allow you to write a class or method that can work with any data type.
- System.Collection.Generic namespace contains Collection<T>, Dictionary<TKey, TValue>, List<T>, Queue<T>, Stack<T>

Type Safety Example
ArrayList obj = new ArrayList();
obj.Add(50);
obj.Add("Dog");
obj.Add(new TestClass());

foreach(int i in obj) Console.WriteLine(i);
//the code will compile, but run time iteration will through 'InvalidCastException' occurred when it print "Dog", bcz it is not integer, the code will print 50.

GenericClass<int> intObj = new GenericClass<int>();
intObj.setItem(0, 50);
intObj.setItem(1, "Dog"); //compiler error, the compiler doesn't compile the code.

Performance
Generics are faster than other collections such as ArrayList. In non-generic colloection, boxing and unboxing overhead when a value type is converted to reference type and vice-versa.

ArrayList  obj = new ArrayList();
obj.Add(50);    //boxing- convert value type to reference type
int x= (int)obj[0]; //unboxing

GenericClass<int>, an int type is generated dynamically from the compiler, boxing and unboxing no longer occurs.

GenericClass<int> obj = new GenericClass<int>();
obj.Add(50);    //No boxing
int x= obj[0]; // No unboxing

Code reuse - A Generic class can be defined once and can be instantiated with many different types.
GenericClass<int> intObj = new GenericClass<int>();
GenericClass<char> charObj = new GenericClass<char>();        

Generic Class Example
using System;
using System.Collections.Generic;

namespace GenericClassApplication
{
   public class GenericClass<T>
   {
      private T[] obj = new T[5]; // define an Array of Generic type with length 5
   
      public T getItem(int index)
      {
         return obj[index];
      }
   
      public void setItem(int index, T value)
      {
         obj[index] = value;
      }
   }
 
   class Program
   {
      static void Main(string[] args)
      {
//instantiate generic with int
         GenericClass<int> intObj = new GenericClass<int>();
         for (int i = 0; i < 5; i++) intObj.setItem(i, i*2);
         for (int i = 0; i < 5; i++) Console.WriteLine(intObj.getItem(i)); //0 2 4 6 8
       
         //instantiate generic with char
         GenericClass<char> charObj = new GenericClass<char>();      
         for (int i = 0; i < 5; i++) charObj.setItem(i, (char)(i*2));
         for (int i = 0; i < 5; i++) Console.WriteLine(charObj.getItem(i));
      }
   }
}


Generic Methods Example
using System;
using System.Collections.Generic;

namespace GenericMethodApplication
{
   class Program
   {
      static void Swap<T>(ref T a, ref T b)
      {
         T temp;
         temp = a;
         a = b;
         b = temp;
      }
   
      static void Main(string[] args)
      {
         int a=10, b=20; //a = 10, b = 20
Swap<int>(ref a, ref b); //a = 20, b = 10

         char i = 'I', j ='J';
         Swap<char>(ref i, ref j); //i = 'J', j = 'I'
      }
   }
}

Generic Delegates Example
using System;
using System.Collections.Generic;

delegate T GenericDelegate<T>(T n);
namespace GenericDelegateApplication
{
   class DelegateClass
   {
      static int n = 10;
      public static int Sum(int i)
      {
         n += i;
         return n;
      }
   
      public static int Times(int i)
      {
         n *= i;
         return n;
      }
      public static int getValue()
      {
         return n;
      }
   
      static void Main(string[] args)
      {
         //create delegate instances
         GenericDelegate<int> gd1 = new GenericDelegate<int>(Sum);
         GenericDelegate<int> gd2 = new GenericDelegate<int>(Times);
       
         gd1(5); //calling the methods using the delegate objects,
         getValue(); //15
       
         gd2(2);
         getValue(); //30
      }
   }
}

Boxing - Boxing is used to store value types in the garbage-collected heap. A referece type is allocated on the heap.
int i = 123;
object o = i; //implicit conversion of a value type to the reference type (object).

stack heap

i
-----
| 23 |
-----
int i=123;

o
---                -----
|     |--------->  |int |
---                |----|
object o =i;     |123 |
       -----

Unboxing -  an explicit conversion from the reference type(object) to a value type. A value type is allocated on the stack
int j = int(o);

j
-----
| 23 |
-----
int j =(int)o;

No comments: