Generics - 4.3 Replacing the ArrayList with Its Generic Counterpart
(Page 3 of 4 )
Problem
You want to enhance the performance of your application as well as make the code easier to work with by replacing all ArrayList objects with the generic version. This is imperative when you find that structures or other value types are being stored in these data structures, resulting in boxing/unboxing operations.
Solution
Replace all occurrences of the System.Collection.ArrayList class with the more efficient generic System.Collections.Generic.List class.
Here is a simple example of using aSystem.Collections.ArrayListobject:
public static void UseNonGenericArrayList()
{
// Create and populate an ArrayList.
ArrayList numbers = new ArrayList();
numbers.Add(1); // Causes a boxing operation to occur
numbers.Add(2); // Causes a boxing operation to occur
// Display all integers in the ArrayList.
// Causes an unboxing operation to occur on each iteration
foreach (int i in numbers)
{
Console.WriteLine(i);
}
numbers.Clear();
}
Here is that same code using aSystem.Collections.Generic.Listobject:
public static void UseGenericList()
{
// Create and populate a List.
List<int> numbers = new List<int>();
numbers.Add(1);
numbers.Add(2);
// Display all integers in the ArrayList.
foreach (int i in numbers)
{
Console.WriteLine(i);
}
numbers.Clear();
}
Discussion Since ArrayLists are used in almost all applications, it is a good place to start to enhance the performance of your application. For simple implementations of the ArrayList in your application, this substitution should be quite easy.
Table 4-1 shows the equivalent members that are implemented in both classes.
Table 4-1. Equivalent members in the ArrayList and the generic List classes
| Members in the ArrayList class | Equivalent members in the generic List class |
| Capacityproperty | Capacityproperty |
Countproperty | Countproperty |
IsFixedSizeproperty | ((IList)myList).IsFixedSize |
IsReadOnlyproperty | ((IList)myList).IsReadOnly |
IsSynchronizedproperty | ((IList)myList).IsSynchronized |
Itemproperty | Itemproperty |
SyncRootproperty | ((IList)myList).SyncRoot |
Adapter staticmethod | N/A |
Addmethod | Addmethod |
AddRangemethod | AddRangemethod |
N/A | AsReadOnlymethod |
BinarySearchmethod | BinarySearchmethod |
Clearmethod | Clearmethod |
Clonemethod | GetRange(0, numbers.Count) |
Table 4-1. Equivalent members in the ArrayList and the generic List classes (continued)
Containsmethod | Containsmethod |
N/A | ConvertAllmethod |
CopyTomethod | CopyTomethod |
N/A | Existsmethod |
N/A | Findmethod |
N/A | FindAllmethod |
N/A | FindIndexmethod |
N/A | FindLastmethod |
N/A | FindLastIndexmethod |
N/A | ForEachmethod |
FixedSize staticmethod | N/A |
GetRangemethod | GetRangemethod |
IndexOfmethod | IndexOfmethod |
Insertmethod | Insertmethod |
InsertRangemethod | InsertRangemethod |
LastIndexOfmethod | LastIndexOfmethod |
ReadOnlystatic method | AsReadOnlymethod |
Removemethod | Removemethod |
N/A | RemoveAllmethod |
RemoveAtmethod | RemoveAtmethod |
RemoveRangemethod | RemoveRangemethod |
Repeatstatic method | Use a forloop and the Addmethod |
Reversemethod | Reversemethod |
SetRangemethod | InsertRangemethod |
Sortmethod | Sortmethod |
Synchronizedstatic method | lock(myList.SyncRoot){…} |
ToArraymethod | ToArraymethod |
N/A | TrimExcessmethod |
TrimToSizemethod | TrimToSizemethod |
N/A | TrueForAllmethod |
In several cases within Table 4-1, there is not a one-to-one correlation between the members of an ArrayList and the members of the generic List class. Starting with the properties, notice that only the Capacity,Count, andItemproperties are present in both classes. To make up for the missing properties in theListclass, you can perform a cast to anIList. The following code shows how to use these casts to get at the missing properties:
List<int> numbers = new List<int>();
Console.WriteLine(((IList)numbers).IsReadOnly);
Console.WriteLine(((IList)numbers).IsFixedSize);
Console.WriteLine(((IList)numbers).IsSynchronized);
Console.WriteLine(((IList)numbers).SyncRoot);
Note that due to the absence of code that returns a synchronized version of a genericListand the absence of code that returns a fixed-size genericList, theIsFixedSizeandIsSynchronizedproperties will always returnfalse. TheSyncRoot property will always return the same object on which it is called. Essentially, this property returns thethispointer. Microsoft has decided to remove the ability to create a synchronous wrapper from any of the generic collection classes. Instead, they recommend using thelockkeyword to lock the entire collection or another type of synchronization object that suits your needs.
TheArrayList has several static methods to which there is no direct equivalent method in the genericListclass. To fix this, you have to do a little work. The closest match for the staticArrayList.ReadOnlymethod is theAsReadOnlyinstance method of the genericList class. This makes for a fairly simple substitution.
The staticArrayList.Repeatmethod has no direct equivalent in the genericListclass. So instead, you can use the following generic extension method:
public static void Repeat<T>(this List<T>list, T obj, int count)
{
if (count < 0)
{
throw (new ArgumentException(
"The count parameter must be greater or equal to zero."));
}
for (int index = 0; index < count; index++)
{
list.Add(obj);
}
}
This generic extension method has three parameters:
list
Marks this method as an extension method forList<T>.
obj
The object that will be added to the genericList
object a specified number of times.
count
The number of times to add the object contained in
objto the genericListobject.
Since theClonemethod is also missing from the genericListclass (due to the fact that this class does not implement theICloneableinterface), you can instead use theGetRangemethod of the genericListclass:
List<int> oldList = new List<int>();
// Populate oldList...
List<int> newList = oldList.GetRange(0, oldList.Count);
TheGetRangemethod performs a shallow copy (similar to theClone method of theArrayList) of a range of elements in theListobject. In this case, the range of elements includes all elements.
See Also The “System.Collections.ArrayList Class” and “System.Collections.Generic.List Class” topics in the MSDN documentation.
Next: 4.4 Replacing the Stack and Queue with Their Generic Counterparts >>
More C# Articles
More By O'Reilly Media
|
This article is excerpted from chapter four of the C# 3.0 Cookbook, Third Edition, written by Jay Hilyard and Stephen Teilhet (O'Reilly, 2008; ISBN: 059651610X). Check it out today at your favorite bookstore. Buy this book now.
|
|