Working with Collections – Generic IList

I am writing this article directly in response to Working with Collections – ArrayList which obviously about the array list class. Now I’m going to make a blanket statement that includes the word NEVER, generally a statement using never or always tends to be factually inaccurate for how absolute those 2 words are, however I am going to make the statement anyway.

You should NEVER use the ArrayList class.

This class should even be as far as marked deprecated since the introductions of generics a long way back with the release of 2.0 framework. Now I’m sure there’s been many articles that have beat the usage of generics into the ground but here I will make one to explain how to use List<type> class instead of the ArrayList class.

Firstly, what are generics?

Generics were added to the framework as a way to create classes that can contain any type of object while working with it strongly typed and not down casting it to System.Object the way that ArrayList does. Classes that follow patterns like ArrayList will cause objects to be repeatedly boxed and unboxed.

int i = 123;
object o = (object)i;  // boxing

o = 123;
i = (int)o;  // unboxing

Boxing

Boxing is used to store value types in the garbage-collected heap. Boxing is an implicit conversion of a value type to the type object or to any interface type implemented by this value type. Boxing a value type allocates an object instance on the heap and copies the value into the new object.

Performance

In relation to simple assignments, boxing and unboxing are computationally expensive processes. When a value type is boxed, a new object must be allocated and constructed. To a lesser degree, the cast required for unboxing is also expensive computationally. For more information, see Performance.

For further information on boxing see the MSDN.

Now that you have a clearer understanding of what boxing is if you think about the ArrayList class since you can insert any type of object into the list with reckless abandon every single addition and read from the list will cause un/boxing to occur. With the statements above it’s clear to see why in usage this is a very poor class to use.

Adding

The List class also supports the inserting of strings in the same way that ArrayList does both with the Add() and AddRange() methods. I will show examples of both the .NET 2.0 usage and new conventions for the 3.5 usages.

List<string> strings20 = new List<string>();
const string dotnetchris = "dotNetChris";

strings20.Add("Marisic.Net");
strings20.Add(dotnetchris);

//Build error: Argument Type 'object' is not assignable to parameter type 'string'
strings20.Add((object)dotnetchris);

//.Net 3.5 added the var keyword and the ability to initialize a list easily.
var strings35 = new List<string> {"initial", "strings", "loaded"};

As you can see in 3.5 creating a collection with initial data much easier. It also doesn’t allow boxing to occur as you can not even add a string object if you down cast it to Object.

var stringsCombined = new List<string>();
stringsCombined.AddRange(strings20);
stringsCombined.AddRange(new[] {"string1", "string2"});

With the AddRange() method you can add any class that implements ICollection which is an interface defining a common usage of a list structure so List<> and arrays are the most common implementers of ICollection.

Now lets add in some LINQ!

strings35.AddRange(from stringval in stringsCombined
                   where stringval.StartsWith("s")
                   select stringval);
//strings35 now has: "inital", "strings", "loaded", "string1", "string2"

LINQ expressions can be used to select specific data from our lists and then make it a list itself which you could assign to it’s own declaration or use in AddRange()!

Insert

The correlary to Add and AddRange methods are the Insert and InsertRange I will move usage of these and that you can index through Lists quickly. With insert you can choose where an item is inserted into the List where as Add/Range will always place the item(s) to the end of the list.

var numbers = new List<int> {2, 2, 4};
numbers.Insert(0, 1);
numbers[2]++;
//numbers now has: 1 2 3 4

Remember that indexers are always 0 based with the Microsoft classes So Insert(0, 1) will insert on the index 0 the value of 1.

//ArgumentOutOfRangeException always remember Count - 1
numbers[numbers.Count] = 5;

Always keep indexers in mind to avoid this from occurring.

At this point I am going to hand the ball back to the article that started this post that you see the usage of Iterating through a list, removing objects and a few other helpful functions. I’ve shown some new features that were added in 3.5 that makes working with lists even greater and easier than ever. In my next post I will go over usage of some of the more complicate functions on the List class that take a paraemter of Predict<T> and the lamba operator.

BloggingContext.ApplicationInstance.CompleteRequest();

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s