Sunday, February 26, 2012

Arrays and Arraylist in .NET

So far we have been discussing the fundamentals of object oriented programming, difference between interfaces, abstract classes, enumerations, structures etc. Today, we will talk about using arrays and arraylists to store various objects and difference between the two.

Both arrays and arraylists are stored on a heap. Even if you store value types in an array or an arraylist, the values are implicitly converted to reference types (boxing) and you must explicitly convert them back to proper value types (unboxing) when using them.

Since the items stored in an array or an array list are objects, you can use them to also store reference to objects. For example,

consider the following class...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApp1
{
    class Student
    {
      
     private string _name;
     private string _address;
     private int _studentID;
     public string Name
     {
          get {return _name;}
          set {_name=value;}
     }
     public string Address
     {
          get {return _address;}
          set {_address=value;}
     }
     public int StudentID
     {
          get {return _studentID;}
          set {_studentID=value;}
     }
  }
    
}

Now let's use an array to store several references of these objects.

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            //Using an Array
 
            //first instance
             Student student1 = new Student();
             student1.Name = "Student One";
             student1.Address = "123, Peachtree Road, Atlanta, GA 30303";
             student1.StudentID = 1;
            //second instance
             Student student2 = new Student();
             student2.Name = "Student Two";
             student2.Address = "456, Peachtree Road, Atlanta, GA 30303";
             student2.StudentID = 2;
            //third instance
             Student student3 = new Student();
             student3.Name = "Student Three";
             student3.Address = "678, Peachtree Road, Atlanta, GA 30303";
             student3.StudentID = 3;

             //instantiate an array to store these objects.
             Student[] StudentsList = new Student[2];
             StudentsList[0] = student1;
             StudentsList[1] = student2;
             StudentsList[2] = student3;

            //since array is already of type Student, no typecasting is necessary.
            Console.WriteLine(StudentsList[0]);

       }
    }
}

There are several problems with this approach. First, you have to initialize an array and specify its size. Which means you have to know how many objects you are going to store in an array beforehand. Second limitation is that an array must be specific to the type you are going to store, meaning you cannot store two different types of objects in an array. Also, once an array has been initialized to a specific size, you cannot resize it downwards.

Now let's consider the same example using an arraylist.

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
             
            //first instance
             Student student1 = new Student();
             student1.Name = "Student One";
             student1.Address = "123, Peachtree Road, Atlanta, GA 30303";
             student1.StudentID = 1;
            //second instance
             Student student2 = new Student();
             student2.Name = "Student Two";
             student2.Address = "456, Peachtree Road, Atlanta, GA 30303";
             student2.StudentID = 2;
            //third instance
             Student student3 = new Student();
             student3.Name = "Student Three";
             student3.Address = "678, Peachtree Road, Atlanta, GA 30303";
             student3.StudentID = 3;

            //instantiate an arraylist to store these objects.
             ArrayList StudentList = new ArrayList();   
            
            // notice an arraylist isn't of a specifc type.
             StudentList.Add(student1);
             StudentList.Add(student2);
             StudentList.Add(student3);

            //since arraylist is a generic list, you must type cast it first.
            Console.WriteLine((Student)(StudentList[0]));

            //Arraylist allows for inserting an object at a specific position.

             //fourth instance
             Student student4 = new Student();
             student4.Name = "Student Four";
             student4.Address = "890, Peachtree Road, Atlanta, GA 30303";
             student4.StudentID = 4;
             StudentList.Insert(1, student4);

            //You can also remove an object from an array list
             StudentList.Remove(student4); // remove a specific object
            //OR
             StudentList.RemoveAt(2);   //remove whatever is at index 2
     
        }
    }
}

As you can see, an arraylist avoids some of the problems of an array. First, an arraylist doesn't have to be sized and resized. An element can be added or removed from an arraylist.

Note, since an arraylist isn't cast into a specific type during declaration, when reading the content from an arraylist, you must explicitly cast to a specific type, as show in the above code snippet.

An arraylist also allows for inserting an object at any position, including the position where an object may already exist. If you insert an element at a position already occupied by another element, the current element will simply push down.

Since an arraylist isn't of a particular type, you can add elements of reference or value types in an array, even mixing them.

For example you can do the following.

StudentList[0] = student1;
StudentList[1] = 5;
StudentList[2] = "This is a test";
StudentList[3] = student2;

But if you add objects of different types or value types in the same arraylist, you must first inspect the element to determine its type before casting it to the appropriate type. This is not only cumbersome and error prone, it also adds an unnecessary overhead.

To write out the content from the above example, you now have to do the following...

if (StudentList[1].GetType() == typeof(int))
   {
    //do something
   }

This becomes unusable pretty quickly. So, what should you do to get the flexibility of an arraylist without the added overhead? In the next post we will talk about generic collections and how they can aid us in a situation like this.

No comments:

Post a Comment