Friday, November 20, 2009

Sorting List of Custom Objects

“System.Collections” and “System.Collections.Generic “ namespaces have classes for collections. Collection objects are the specialized objects which can hold multiple objects of other classes. Other classes also refer to collection classes along with non-collection classes. The two different namespaces have non-generic and generic versions of collection classes.
My discussion is focusing on the ArrayList collection class. This discussion also covers the generic version “List<T>"class.

What is ArrayList?
ArrayList is a non-generic collection class. Object of this class can hold list of homogeneous objects. Homogeneous objects means objects of any class (data type). This collection may not have necessarily objects of same type.

ArrayList grows dynamically with addition of new objects. It does not have any fixed length. Initially, empty ArrayList object has capacity of 0 objects. As we add first object, the capacity grows to hold 4 objects. When we add the fifth object, it grows by double to hold 8 objects in it. ArrayList capacity doubles when its capacity is crossed.

List<T> is just the generic version of ArrayList. Generic collection object can have objects of same type only.

Sorting:

ArrayList and List have the sort method already implemented. This sort method works very well for primitive system data types (e.g. int, long etc.). But what about the user-defined types (viz. Class, Struct,Enum)? To order the objects you should know how to compare them. How to acquaint .NET Framework about comparing user-defined data types?

public class Person
{
public string Name;
public int Age;
}
List<person> plist=new <Person>();
… //Add few person objects.
plist.Sort();

Consider we’ve the list of person objects. How sorting will happen, based on Name or Age? What it’ll compare (name or age of persons)? Try it.


Comparison of Person object is possible only if we implement IComparable or IComparer interface. The IComparable interface has single method, CompareTo. See the code below with IComparable interface implementation.


public class Person : IComparable //Change it to IComparable<Person>
{
public string Name;
public int Age;

#region IComparable Members
//Argument will be of Person type if IComparable<Person> is //implemented.
public int CompareTo(Object obj)
{
Person p=obj as Person //Not required if generic IComparable implemented.
return this.Name.CompareTo(p.Name);
}
#endregion
}

IComparable interface has generic variant, IComparable<T> interface. The CompareTo method of IComparable<T> takes object of T as argument. So type-casting of argument is avoided.


Now it’ll sort the Person list with respect to their names. What if we’d like to have the sorting by Age? Change the code.


What if we’d like to have sorting by Age as well as by Name? Then IComparable interface implementation is not sufficed. We’ve to create two implementations (classes) of IComparer interface : NameComparer and AgeComparer. IComparer interface has Compare method accepting two objects. Cast the objects to appropriate type & then compare. Generic version of IComparer is IComparer<T> can be implemented in similar way. It avoids need of type-casting.


NameComparer will have implementation of Compare method based on Name whereas AgeComparer will have implementation based on Age. These classes will not have any other code.


Sort method overload accepts object of IComparer implementation (class) as argument. If our requirement is to compare by Age use object of AgeComparer, or else NameComparer for alphabetical sorting.


public class NameComparer : IComparer
{
#region IComparer Members

public int Compare(object x, object y)
{
Person p = x as Person;
Person q = y as Person;
return p.Name.CompareTo(q.Name);
}

#endregion
}
public class AgeComparer : IComparer
{
#region IComparer Members

public int Compare(object x, object y)
{
Person p = x as Person;
Person q = y as Person;
return p.Age.CompareTo(q.Age);
}

#endregion
}

plist.Sort(new AgeComparer());

That’s all folks!!! Reuse the .NET functionality.

Tuesday, November 3, 2009

Response.Redirect and Server.Transfer

Response.Redirect:

Response is the object which accumulates the HTML/Javascript for the page requested. Each response has an associated Request object. Request object has the information about HTTP request headers and request body. Request body contains posted parameters.



I've used Web Developer helper tool to show you the details of HTTP Request & Response. HTTP request is comprised of HTTP command(e.g. GET,POST HEAD etc.) alongwith HTTP Headers (e.g. User-Agent) and the request body,if any. Request body appears only if user is posting some selections / values back to HTTP server. Diagram (1) shows you the details of HTTP Request.


The image below shows the GET Request body.



The images below show the POST request with Request body





If Response.Redirect is used to change the page to be shown, there is no access method available to access the posted values on second page. The reason : Response.Redirect involves round-trip to redirect the browser to new page. Browser redirection to new page has new request. Request body of first request of the round-trip lost unprocessed.



Response.Redirect helps to redirect to different server. Page on test.com can be redirected to google.com.



In essence, Response.Redirect involves one round-trip with two different requests. Response.Redirect loose the first-request body. Use Response.Redirect to redirect the browser to some page of different server. For same server, my suggestion is to use hyperlink or Server.Transfer.


Server.Transfer:

Server object represents the server processing request. Server.Transfer cannot transfer to the page of different server. Server.Transfer does not involve any round-trip. Request body is available to new page (of same server)as no round-trip involves.