converted your code to use the latest .net 3.5 features... generally its frowned upon to create an arraylist of objects. the problem being that, the IDE can no longer give you intellisense. neither can the compiler do any type checking for you. you basically loose two very important features that make .net development easy.
An arraylist is meant to store objects. now, even though we have created our custom class, our ObjNeeded objects will get boxed into the Object object as and when we add items to the arraylist. If the term boxing sounds confusing, think of it as typecasting, but very needlessly expensive.
Everytime we iterate over the arraylist, we will have to unbox each element to get our original ObjNeeded object back. Thus, we are unnecessarily boxing and unboxing our object. there is supposedly a high performance penalty on these operations.
These performance claims might not sound convincing. So let me move on to type safety. The System.Object class is the ultimate base class for all classes in .Net. By the property of
covariance, any method which will accept a parameter of type System.Object will also accept an object of any .Net class. So, some user can actually write code like the below: [am only posting the excerpts]
GeSHi (C#):
ArrayList AL = new ArrayList();
AL.Add(new ObjNeeded(1, "Ye"));
AL.Add(new ObjNeeded(2, "shall"));
AL.Add(new CrappyClass("get")); // <------ This will compile and build ...
AL.Add(new CrappyClass("screwed!!"));
....
ObjNeeded o;
for (int i = 0; i < AL.Count; i++)
{
o = (ObjNeeded)AL[i];
Console.WriteLine(o.index + ") " + o.value); // <----- So will this... But, when you try executing it, kaboom!!
}
....
class CrappyClass
{
public string msg;
public CrappyClass(string msg)
{
this.msg = msg;
}
}
Created by GeSHI 1.0.8.2
There are two problems here. Because the arraylist has been defined to only accept objects, the call where we add a CrappyClass object is very much a valid statement. The compiler has no idea, nor the user has any idea that the arraylist is only supposed to contain ObjNeeded objects...
The second problem is when we are iterating over the arraylist. again, because the arraylist contains the all encompassing System.Object objects, it allows us to typecast it back to ObjNeeded objects. But when we reach the CrappyClass objects, the typecasting will not work and we will get a InvalidCastException. The compiler is not able to catch this, because at no point of time we are restricting the type of the objects that can be stored in the arraylist.
If we try viewing the intellisense on just the AL object, without typecasting each element, we cannot realize what the original type of the object was. For that we will have to use reflection or we will have to first check what the type of the object is, if it matches the type ObjNeeded, then typecast it, else ignore it.
GeSHi (C#):
for (int i = 0; i < AL.Count; i++)
{
if (AL[i].GetType().Equals(typeof(ObjNeeded)))
{
o = (ObjNeeded)AL[i];
Console.WriteLine(o.index + ") " + o.value);
}
}
Created by GeSHI 1.0.8.2
Now ideally, we shouldnt have to jump through so many hoops just to have a dynamic array of objects. And thankfully, since .net 2.0, we dont have to.
Everyone welcome
Generics!!
The article that i linked to, albeit a bit long, has explained the reasons for using generics better than i could have. I will assume that most are familiar with generics or can atleast understand what is going on from the source.
GeSHi (C#):
List<ObjNeeded> AL = new List<ObjNeeded>();
Created by GeSHI 1.0.8.2
the above explicitly describes to the compiler that the list AL can only contain objects of type ObjNeeded. if we try adding any other type of object, the code wouldnt compile. Because we know that the compiler will not allow any object apart from the ones we want in the list, we can remove the code for type checking and simply iterate over it.
Below is the final code [btw, besides generics i have also used collection and object initializers, automatically implemented properties, etc... i believe sam has touched upon these in his previous posts]
GeSHi (C#):
using System;
using System.Collections.Generic;
public class TestClass
{
public static void Main()
{
List<ObjNeeded> AL = new List<ObjNeeded>()
{
new ObjNeeded { Index=1, Value="Ye"},
new ObjNeeded { Index=2, Value="Shall"},
new ObjNeeded { Index=3, Value="Know"},
new ObjNeeded { Index=4, Value="The"},
new ObjNeeded { Index=5, Value="Truth"},
new ObjNeeded { Index=6, Value="And"},
new ObjNeeded { Index=7, Value="The"},
new ObjNeeded { Index=8, Value="Truth"},
new ObjNeeded { Index=9, Value="Shall"},
new ObjNeeded { Index=10, Value="Set"},
new ObjNeeded { Index=11, Value="You"},
new ObjNeeded { Index=12, Value="Free"}
};
Console.WriteLine("Count: {0}", AL.Count);
Console.WriteLine("Capacity: {0}", AL.Capacity);
Console.WriteLine("Values: ");
foreach (ObjNeeded o in AL)
{
Console.WriteLine(o.Index + ") " + o.Value);
}
Console.Write("\nExecution Ended.");
Console.ReadKey();
}
}
class ObjNeeded
{
public int Index {get; set;}
public string Value {get; set;}
public ObjNeeded()
{
Index = -1;
Value = "uninitialized";
}
}
Created by GeSHI 1.0.8.2