Sunday, December 19, 2010

Generics in .NET

Download Generics Source Code 

Generics  are part of the type system of the CLR that allow you to define a type while leaving

some details unspecified. Instead of specifying the types of certain parameters or
members, you can allow code that uses your generic class to specify those types. This
allows consumer code to tailor your class to meet specific needs of the consumer code.

The .NET Framework includes several generic classes in the
System.Collections.Generic
namespace, including
work similarly to their nongeneric counterparts in
improved performance and type safety.

Why Use Generics?
Generics offer two significant advantages over using the
object class:
��
to and from the
and then attempt to cast that
the error. Instead, the application throws an exception at run time. Using generics
allows the compiler to catch this type of bug before your program runs. In
addition, you can specify constraints to limit the classes used in a generic,
enabling the compiler to detect an incompatible type being called for by consumer
code.
Reduced run-time errors The compiler cannot detect type errors when you castObject class. For example, if you cast a string to an Object classObject to an integer, the compiler does not catch
��
doesn’t require casting or boxing, so run-time performance improves

How to Create a Generic Type
First, examine the following classes. Classes
tasks, but
Obj and Gen perform exactly the sameObj uses the Object class to enable any type to be stored in its field, while
Gen
uses generics:
' VB
Class Obj

Public V1 As Object
Public V2 As Object
    Public Sub New(ByVal _V1 As Object, ByVal _V2 As Object)
          V1 = _V1
           V2 = _V2
    End Sub
End Class

Class Gen(Of T, U)

    Public V1 As T
    Public V2 As U
    Public Sub New(ByVal _V1 As T, ByVal _V2 As U)
        V1 = _V1
        V2 = _V2
    End Sub
End Class

// C#
class Obj
{
       public Object t;
        public Object u;
        public Obj(Object _t, Object _u)
        {
            t = _t;
            u = _u;
         }
}

class Gen<T, U>
{
           public T t;
           public U u;
           public Gen(T _t, U _u)
          {
               t = _t;
               u = _u;
           }
}

As you can see, the
field members of type
Obj class has two members of type Object. The Gen class has twoT and U. The consuming code determines the types for T and
U
. Depending on how the consuming code uses the Gen class, T and U could be a
string
There is a significant limitation to creating a generic class (without constraints, as discussed
in the section “How to Use Constraints,” later in this chapter): Generic code is
valid only if it compiles for every possible constructed instance of the generic,
whether an
of the base
, an int, a custom class, or any combination thereof.Int, a string, or any other class. Essentially, you are limited to the capabilitiesObject class when writing generic code. Therefore, you could call the
ToString
or the
because the consuming code declares a specific type for the generic.

How to Consume a Generic Type
When you consume a generic type, you must specify the types for any generics used.
Consider the following Console application code, which uses the
Gen and Obj classes:
' VB
' Add two Strings using the Obj class
Dim oa As Obj = New Obj("Hello, ", "World!")
Console.WriteLine(CType(oa.V1, String) + CType(oa.V2, String))

' Add two Strings using the Gen class
Dim ga As New Gen(Of String, String)("Hello, ", "World!")
Console.WriteLine(ga.V1 + ga.V2)

' Add a Double and an Integer using the Obj class
Dim ob As Obj = New Obj(10.125, 2005)
Console.WriteLine(CType(ob.V1, Double) + CType(ob.V2, Integer))

' Add a Double and an Integer using the Gen class
Dim gb As New Gen(Of Double, Integer)(10.125, 2005)
Console.WriteLine(gb.V1 + gb.V2)

// C#

// Add two strings using the Obj class
Obj oa = new Obj("Hello, ", "World!");
Console.WriteLine((string)oa.t + (string)oa.u);

// Add two strings using the Gen class
Gen<string, string> ga = new Gen<string, string>("Hello, ", "World!");
Console.WriteLine(ga.t + ga.u);

// Add a double and an int using the Obj class
Obj ob = new Obj(10.125, 2005);
Console.WriteLine((double)ob.t + (int)ob.u);

// Add a double and an int using the Gen class
Gen<double, int> gb = new Gen<double, int>(10.125, 2005);
Console.WriteLine(gb.t + gb.u);
If you run that code in a Console application, the
the same results. However, the code that uses the
because it does not require boxing and unboxing to and from the
and unboxing are discussed in the section “What Are Boxing and Unboxing?” later in
this chapter.) In addition, developers would have a much easier time using the
Obj and Gen classes produce exactlyGen class actually works fasterObject class. (BoxingGen
class. First, developers would not have to cast manually from the
appropriate types. Second, type errors would be caught at compile time rather than at
run time. To demonstrate that benefit, consider the following code, which contains an
error (shown in bold):
Object class to the
' VB
' Add a Double and an Integer using the Gen class

Dim gb As New Gen(Of Double, Integer)(10.125, 2005)
Console.WriteLine(gb.V1 + gb.V2)

' Add a Double and an Integer using the Obj class

Dim ob As Obj = New Obj(10.125, 2005)
Console.WriteLine(CType(ob.V1,
 
// C#

// Add a double and an int using the Gen class

Gen<double, int> gc = new Gen<double, int>(10.125, 2005);
Console.WriteLine(gc.t + gc.u);

// Add a double and an int using the Obj class
Obj oc = new Obj(10.125, 2005);
Console.WriteLine((int)oc.t + (int)oc.u);
Integer) + CType(ob.V2, Integer))
Real time example:

Class1.cs
=======
using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace
{

{



{
t=_t;
u= _u;
}
}
WebApplication1public class Gen<T,U>public T t;public U u;public void gen(T _t,U _u)public class Obj{



{
a = _a;
b = _b;
}
}
public object a;public object b;public void obj(object _a, object _b)public class compareGen<T> where T : IComparable{



{
t1 = _t1;
t2 = _t2;
}

{

{

}
public T t1;public T t2;public void compGen(T _t1, T _t2)public T Max()if (t2.CompareTo(t1) < 0)return t1;else{

}
}
}
}
return t2;


Default.aspx.cs:
============
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;namespace
{
WebApplication1public partial class _Default : System.Web.UI.Page{

{

ob.obj(
Response.Write((

he.gen(
Response.Write(

ri.gen(
Response.Write(
}

{

compare.t1 =
compare.t2 =
TextBox3.Text = compare.Max().ToString();
}

{

strin.t1 = TextBox1.Text;
strin.t2 = TextBox3.Text;
TextBox3.Text = strin.Max();
}
}
}
protected void Page_Load(object sender, EventArgs e)Obj ob = new Obj();"Hello", "World!");string)ob.a + (string)ob.b);Gen<string, string> he = new Gen<string, string>();"Myworld", "Hello");"\n"+he.u + he.t);Gen<string, int> ri = new Gen<string, int>();"My number is: ", 420);"\n"+ri.t + ri.u);protected void Button1_Click(object sender, EventArgs e)compareGen<int> compare = new compareGen<int>();Convert.ToInt32(TextBox1.Text);Convert.ToInt32(TextBox2.Text);protected void Button2_Click(object sender, EventArgs e)compareGen<string> strin = new compareGen<string>();

Output:
HelloWorld!
HelloMyworld
My number is: 420
Comparing Two numbers by using IComparable interface in Gerneric Class
 
How to Use Constraints
Generics would be extremely limited if you could only write code that would compile
for any class, because you would be limited to the capabilities of the base
To overcome this limitation, use constraints to place requirements on the types that
consuming code can substitute for your generic parameter.
Generics support four types of constraints:
��
generic type argument

Interface Allows only types that implement specific interfaces to be used as a
��
be used as a generic type argument

Base class Allows only types that match or inherit from a specific base class to
��
to implement a parameterless constructor

Constructor Requires types that are used as the type argument for your generic
��
your generic to be either a reference or a value type
Reference or value type Requires types that are used as the type argument for
Reference or value type Requires types that are used as the type argument forAs clause in Visual Basic or the where clause in C# to apply a constraint to aIComparable interface:
' VB
Class CompGen(Of T As IComparable)
Public t1 As T
Public t2 As T
Public Sub New(ByVal _t1 As T, ByVal _t2 As T)
t1 = _t1
t2 = _t2
End Sub
Public Function Max() As T
If t2.CompareTo(t1) < 0 Then
Return t1
Else
Return t2
End If
End Function
End Class
// C#
class CompGen<T>
where T : IComparable
{
public T t1;
public T t2;
public CompGen(T _t1, T _t2)
{
t1 = _t1;
t2 = _t2;
}
public T Max()
{
if (t2.CompareTo(t1) < 0)
return t1;
else
return t2;
}
}
The preceding class compiles correctly. However, if you remove the As/where clause,
the compiler returns an error indicating that generic type T does not contain
a definition for CompareTo. By constraining the generic to classes that implement
IComparable
 , you guarantee that the CompareTo method will always be available.
public object a;public object b;public void obj(object _a, object _b)
or GetHashCode method within your class, but you could not use the + operator> operator. These same restrictions do not apply to the consuming code
Improved performance Casting requires boxing and unboxing, which steals processor time and slows performance. Using generics
Dictionary, Queue, SortedDictionary, and SortedList. These classesSystem.Collections, but they offer

No comments:

Post a Comment