Introduction
Generics are new feature provided with version 2.0 of the Microsoft.Net framework. Generic classes and methods combine re-usability, type safety and efficiency in a way that there non-generics counterparts do not/cannot.
In this part some features of ArrayLists and there shortcomings/limitations will be discussed. The codein this article has been written in Visual Studio 2005 in C#.
Earlier ArrayLists used to server the purpose, but that in a certain limit. Moreover, using ArrayLists to store different types came as a good performance cost. At the client end it shows our desired type that we are storing in the ArrayList but internally there's much more that goes on.
Example
System.Collections.ArrayList myList = new System.Collections.ArrayList();
myList.Add(22);
myList.Add("C# Generics");
myList.Add(22.45);
The usage convenience that is perceived above comes at a cost. Any reference or value type that is stored or added in the ArrayList (myList) is implicitly upcasted to System.Object type. And while retrieval, the reverse happens- downcasting to the appropriate type takes place.
Moreover, there is compromise on the Type Safety front also. Consider the code below
int item = 0;
// This will cause an InvalidCastException
foreach (int x in myList)
{
item = item + x;
}
The reason is evident.
In .Net 1.x type-safety was achieved by writing your own typed ArrayList. But again, in that case re-usability was a major issue. Consider the following code.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace ArrayListSample
{
#region Person Class
class Person
{
String Name;
Int32 Age;
String Address;
#region Constructor
public Person() { }
public Person(String Name, Int32 Age, String Address)
{
this.Name = Name;
this.Age = Age;
this.Address = Address;
}
public Person(String Name, Int32 Age)
{
this.Name = Name;
this.Age = Age;
this.Address = String.Empty;
}
public Person(String Name, String Address)
{
this.Name = Name;
this.Age = 0;
this.Address = Address;
}
public Person(String Name)
{
this.Name = Name;
this.Age = 0;
this.Address = String.Empty;
}
#endregion
}
#endregion
#region PeopleCollection Class
class PeopleCollection : IEnumerable
{
private ArrayList arPeople = new ArrayList();
public PeopleCollection()
{
}
#region Methods
public void AddPeople(Person p)
{
arPeople.Add(p);
}
public void ClearPeople()
{
arPeople.Clear();
}
int Count;
public int PeopleCount
{
get { return Count; }
}
#endregion
#region IEnumerable Members
public IEnumerator GetEnumerator()
{
return arPeople.GetEnumerator();
}
#endregion
}
#endregion
class Client
{
public static void Main()
{
PeopleCollection myPeople = new PeopleCollection();
myPeople.AddPeople(new Person("Saurabh", 24, "Gurgaon"));
myPeople.AddPeople(new Person("Manu"));
foreach (Person person in myPeople)
{
Console.WriteLine(person);
}
Console.ReadLine();
}
}
}
The above code does achieve type safety but then we will have to write an almost identical custom collection for each type we wish to contain. Because
myPeople.AddPeople(new Car());
would be a compile time error, since the code/approach above achieves type safety. So at the end of the day it will be a big nightmare !!
So above we find some of the limitations of ArrayLists. In the nextarticle we will find how Generics solve the issues discussed above.