Menus

Showing posts with label Generic List. Show all posts
Showing posts with label Generic List. Show all posts

Tuesday, April 30, 2013

Generic Types in C#


Generic Types

Generics are the most powerful feature of C# 2.0. It allows defining type-safe data structures, without committing to actual data types. In C# 1.0 we can either declare reference type or value type. But in most of the application we come across situation where we need type that can hold both reference & value type. In such situation we use generic types.

Why Generics?
  1. Generic type doesn't care what the type is. We can specify the type at runtime.
  2. It avoids boxing difficulties. In C# 1.0, if we want to put any object into a List, Stack, or Queue objects, we have to take type as System.Object.
  3. It boosts the performance of the application because we can reuse data processing algorithm without duplicating type-specific code.
How Generic implemented:

(1)    Generic type is instantiated at run-time not compiled time
(2)    Generic type are checked at time of declaration not at instantiation
(3)    It works for both reference type & value type.

Let's create simple class "GenericList" using C# 1.0 & 2.0 respectively & compare them.


Code GenericList Class (C# 1.0)

using System;
using System.Collections.Generic;
using System.Text; 
public class GenericList
    {
        private  object[] elements;
        private int count; 
        public GenericList()
        {
            elements = new object[10];
        }
        public object this[int index]
        {
            get { return elements[index]; }
            set { elements[index] = value; }
        } 
        public void Add (object parm)
        {
            if (count == elements.Length)
            {
                  // Increase the
                  object[] tmpArray = null ;
                  elements.CopyTo(tmpArray,0);
                  elements = new object[count * 2];
                  elements = tmpArray;                             
            }
            elements[count] = parm;
            count = count + 1;
        }
   }    

Main Method:

static void Main(string[] args)
        {
            Console.WriteLine("using C# 1.0"); 
            GenericList list = new GenericList();
            list.Add(20);        //Argument is boxed
            list.Add(40);        //Argument is boxed
            list.Add("Sixty");   //Error in retrieving
            Console.WriteLine("Item Added"); 
            int val = (int)list[0]; //Casting required
            Console.WriteLine("Value retrived : " + val); 
        }

Memory Consumption

In C# 1.0 boxing is necessary evil to make type system work. While working with structures of System.Collection namespace (Stacks,List,Hashtable etc) we face the problem in insertion & retrieval of values. We need to take System.object as type & System.object is reference type, so whenever we access the hashtable, the runtime has to box the values to put into the collection & need to unbox to take it out.

list.Add(20);        //Argument is boxed

In C# int takes 4 byte but when it boxed it take (4+8) 12 bytes, which is 3 times to normal size.
In C# 2.0 the type is decided at runtime so boxing does not take place.

Type Safe

When we use the statement

list.Add ("Sixty"); or List [3] = "sixty";

It compiles successfully but later on if some one pulls value and cast it into integer it fails. The problem is fixed in C# 2.0; we will get compilation error there.


Code GenericList Class (C# 2.0)

public class GenericList<T>
    {
        public GenericList()
        {
            elements = new T[10]; 
        } 
        private T[] elements;
        private int count;        
        public T this[int index]
        {
            get {return elements [index];}
            set {elements [index] = value;}
        }    
        public void Add (T parm)
        {
            if (count == elements.Length)
            {
                T[] tmpArray = null;
                elements.CopyTo(tmpArray, 0);
                elements = new T [count * 2];
                elements = tmpArray; 
            } 
            elements [count] = parm;
            count = count + 1;  
        } 
    }

Main Method:

static void Main(string[] args)
{Console.WriteLine("using C# 1.0"); GenericList<int> genericList = new GenericList<int>();genericList.Add (10);          //No boxinggenericList.Add (20);          //No boxing
// genericList.Add("Fifty");   //Compile Time ErrorConsole.WriteLine("Item Added"); int valGeneric = (int)genericList[0]; //No Casting RequiredConsole.WriteLine("Value retrived : " + valGeneric); 
}

Some other Points:

(1) Type parameter can be applied to Class, struct, interface & delegates.
 struct Buket<K, V>; interface ICompare<T>
(2)    Type parameter can have constraints.

Constraint
Description
Public class Books where T: struct
The type argument for class Books must be a value type
Public class Books where T: class
The type argument for class Books must be a reference type
Public class Books where T: new( )
The type argument for class Books must have a public default constructor
Public class Programmer where T: <Employee>
The type argument for class Programmer must be of Employee type.

Thursday, December 13, 2012

Binding custom generic class list to Gridview

Here I will explain how to bind generic list to gridview and how to bind database values to generic list using asp.net. First Create new website and Design your aspx page like this
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Bind Generic List to Gridview</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView runat="server" ID="gvDetails" AutoGenerateColumns="false">
<RowStyle BackColor="#EFF3FB" />
<FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
<PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
<HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
<AlternatingRowStyle BackColor="White" />
<Columns>
<asp:BoundField HeaderText="UserName" DataField="UserName" />
<asp:BoundField HeaderText="FirstName" DataField="FirstName" />
<asp:BoundField HeaderText="LastName" DataField="LastName" />
<asp:BoundField HeaderText="Location" DataField="Location" />
</Columns>
</asp:GridView>
</div>
</form>
</body>
</html>

After that add one class file to your website for that Right click on your website and select Add New Item à one window will open in that select Class file and give name as UserDetails.cs because here I am using this name in my sample if you want to give another name change UserDetails reference name in your sample.
Now open your Class file UserDetails.cs and write the following code
After that write the following code in code behind
public class UserDetails
{
string username = string.Empty;
string firstname = string.Empty;
string lastname = string.Empty;
string location = string.Empty;

public string UserName
{
get { return username; }
set { username = value; }
}

public string FirstName
{
get { return firstname; }
set { firstname = value; }
}

public string LastName
{
get { return lastname; }
set { lastname = value; }
}

public string Location
{
get { return location; }
set { location = value; }
}
}
After completion writing code in your class file open your Default.aspx.cs page add the following namespaces
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
List<UserDetails> objUserDetails = new List<UserDetails>();
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
BindUserDetails();
}
}
protected void BindUserDetails()
{
objUserDetails = GetUserDetails();
gvDetails.DataSource = objUserDetails;
gvDetails.DataBind();
}
protected List<UserDetails> GetUserDetails()
{
string strConnection = "Data Source=SureshDasari;Integrated Security=true;Initial Catalog=MySampleDB";

DataTable dt = new DataTable();
SqlConnection con = new SqlConnection(strConnection);
con.Open();
SqlCommand cmd = new SqlCommand("select * from UserInformation", con);
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
if(dt.Rows.Count>0)
{
for(int i=0;i<dt.Rows.Count;i++)
{
UserDetails userinfo = new UserDetails();
userinfo.UserName = dt.Rows[i]["UserName"].ToString();
userinfo.FirstName = dt.Rows[i]["FirstName"].ToString();
userinfo.LastName = dt.Rows[i]["LastName"].ToString();
userinfo.Location = dt.Rows[i]["Location"].ToString();
objUserDetails.Add(userinfo);
}
}
return objUserDetails;
}