Pages: [1]   Go Down
  Print  
Author Topic: Creating Dynamic Arrays of Objects using ArrayLists  (Read 1250 times)
0 Members and 1 Guest are viewing this topic.
John Anderton
AXIS Core
*****

Karma: +11/-0
Offline Offline

Gender: Male
Posts: 621



View Profile WWW
« on: February 20, 2009, 04:19:22 pm »

I know this is quite basic but I felt this needs to be mentioned in case there is some random traveller on the internet looking for information on this.

First, you should know what ArrayLists are.

Lets have a look at some simple piece of code.
Code
GeSHi (C#):
using System;
using System.Collections;
 
public class TestClass
{
   public static void Main()
   {
       ArrayList AL = new ArrayList();
       AL.Add("Ye");
       AL.Add("shall");
       AL.Add("know");
       AL.Add("the");
       AL.Add("truth");
       AL.Add("and");
       AL.Add("the");
       AL.Add("truth");
       AL.Add("shall");
       AL.Add("set");
       AL.Add("you");
       AL.Add("free");
 
       Console.WriteLine("Count: {0}", AL.Count);
       Console.WriteLine("Capacity: {0}", AL.Capacity);
       Console.Write("Values: ");
 
       for (int i = 0; i < AL.Count; i++)
           Console.Write(AL[i] + " ");
       Console.Write("\n\nExecution Ended.");
       Console.ReadKey();
   }
}
Created by GeSHI 1.0.8.2

Quote from: Output of Sample Code
Count: 12
Capacity: 16
Values: Ye shall know the truth and the truth shall set you free

Execution Ended.

Now that feels quite simple, doesn't it? You have your dynamic array (of strings, in this case).
Lets extend this to objects of a class that you have Smile

The adding of objects is pretty straight forward. To access any of them, just type cast them to an object of the class. Here's a sample Smile

Code
GeSHi (C#):
using System;
using System.Collections;
 
public class TestClass
{
   public static void Main()
   {
       ArrayList AL = new ArrayList();
       AL.Add(new ObjNeeded(1, "Ye"));
       AL.Add(new ObjNeeded(2, "shall"));
       AL.Add(new ObjNeeded(3, "know"));
       AL.Add(new ObjNeeded(4, "the"));
       AL.Add(new ObjNeeded(5, "truth"));
       AL.Add(new ObjNeeded(6, "and"));
       AL.Add(new ObjNeeded(7, "the"));
       AL.Add(new ObjNeeded(8, "truth"));
       AL.Add(new ObjNeeded(9, "shall"));
       AL.Add(new ObjNeeded(10, "set"));
       AL.Add(new ObjNeeded(11, "you"));
       AL.Add(new ObjNeeded(12, "free"));
 
       Console.WriteLine("Count: {0}", AL.Count);
       Console.WriteLine("Capacity: {0}", AL.Capacity);
       Console.WriteLine("Values: ");
 
       ObjNeeded o;
       for (int i = 0; i < AL.Count; i++)
       {
           o = (ObjNeeded)AL[i];
           Console.WriteLine(o.index + ") " + o.value);
       }
 
       Console.Write("\nExecution Ended.");
       Console.ReadKey();
   }
}
 
class ObjNeeded
{
   public int index;
   public string value;
 
   public ObjNeeded(int i, string v)
   {
       index = i;
       value = v;
   }
}
Created by GeSHI 1.0.8.2

Quote from: Output of Sample Code
Count: 12
Capacity: 16
Values:
1) Ye
2) shall
3) know
4) the
5) truth
6) and
7) the
8) truth
9) shall
10) set
11) you
12) free

Execution Ended.

Pretty straight forward, eh? Smile
« Last Edit: February 20, 2009, 04:21:44 pm by John Anderton » Logged

Vi Veri Veniversum Vivus Vici
KarunAB.com || Jatonian Life
Admin (Jan 12th 2008 - July 14th 2008)

strider
Administrator
*****

Karma: +8/-3
Offline Offline

Gender: Male
Posts: 566


Programming is all about expressing yourself...


View Profile
« Reply #1 on: February 21, 2009, 12:13:18 am »

hmm, care to explain the difference bw count and capacity... and what practical use does capacity have, considering we can keep on increasing it...
Logged

strider
Administrator
*****

Karma: +8/-3
Offline Offline

Gender: Male
Posts: 566


Programming is all about expressing yourself...


View Profile
« Reply #2 on: February 21, 2009, 01:38:51 am »

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]

Code
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.

Code
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.

Code
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]

Code
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
Logged

John Anderton
AXIS Core
*****

Karma: +11/-0
Offline Offline

Gender: Male
Posts: 621



View Profile WWW
« Reply #3 on: February 21, 2009, 03:12:45 am »

Sweet Smile My main purpose was to have functions Add and Clear, both of which are available using Lists. And no more need to be worried about the object being put into my List, which is always a relief Smile

Thanks!
Logged

Vi Veri Veniversum Vivus Vici
KarunAB.com || Jatonian Life
Admin (Jan 12th 2008 - July 14th 2008)

anna
AXIS Core
*****

Karma: +7/-0
Offline Offline

Gender: Male
Posts: 122



View Profile
« Reply #4 on: February 22, 2009, 10:12:05 pm »

Greetings...

I too am using ArrayList variables in my code... unnecessary typecasting pains...

Quote from: strider
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.

That explains a lot of things - time for 'find and replace'...thanks man!

Anna
Logged

I'm back!
John Anderton
AXIS Core
*****

Karma: +11/-0
Offline Offline

Gender: Male
Posts: 621



View Profile WWW
« Reply #5 on: April 05, 2009, 08:22:47 pm »

hmm, care to explain the difference bw count and capacity... and what practical use does capacity have, considering we can keep on increasing it...
Count = Actual number of elements in the List/ArrayList right now.
Capacity = Max number it can have without expanding.

A/An List/ArrayList reserves memory for n elements (of type T) at a time where n = 2**i. So if you have 5 elements right now, you can go up to 8 without increasing the amount of memory you would need.

Practical usage? Well.. if you want to keep a limit on the List/ArrayList for some reason or not want it to directly grow, you can monitor the max size count can go up to without expanding by monitoring the property Capacity instead of calculating the next number in the sequence 2**i which is greater than the current value of the property Count.
Logged

Vi Veri Veniversum Vivus Vici
KarunAB.com || Jatonian Life
Admin (Jan 12th 2008 - July 14th 2008)

Pages: [1]   Go Up
  Print  
 
Jump to: