Collection Types - Efficiency

When given a choice, you should always prefer the generic collection types over the nongeneric versions because of added type safety and higher efficiency. Let’s consider the efficiency standpoint a little more closely. When containing value types, the generic types avoid any unnecessary boxing and unboxing. Boxing is definitely a much more expensive operation than unboxing, because boxing requires a heap allocation but an unboxing operation doesn’t. Rico Mariani pinpoints many other efficiency bottlenecks in his blog, Rico Mariani’s Performance Tidbits.8 He indicates that the development teams spent a lot of time focusing specifically on performance issues and simplifying things to make them better. One excellent example that he provides illustrates how List<T> is remarkably faster than ArrayList when used in many foreach iterations. However, the speed is not because of the obvious boxing/unboxing reasons, but rather because ArrayList uses a gratuitous amount of virtual methods, especially during enumeration. ArrayList.GetEnumerator is virtual, and the nested enumerator type ArrayListEnumeratorSimple also implements the MoveNext method and the Current property virtually. That adds up to many costly virtual methods to call during enumeration. Unless you’re enumerating an ArrayList like a crazed demon, you won’t notice this performance penalty, but it just goes to show how much attention the BCL development team has been putting on efficiency lately.

This is a great example of why you want to analyze your class designs clearly to ensure that you’re making your classes inheritable for a good reason. Don’t make a method virtual unless you’re positive someone will need to override it, and if you do, make sure you use the NVI pattern. It is my firm belief that you should tend toward creating sealed classes, unless you’re absolutely sure that there is a good reason why people would want to inherit from your class. If you can’t think of a reason why they would want to, don’t leave it unsealed just because you think someone may come up with a good reason in the future. If you don’t come up with a good reason, then it’s unlikely that you created your class with inheritance in mind, and it may not work as expected for whatever derives from your class. Inheritability should be a conscious decision and not a subconscious one.

There is one caveat to everything mentioned so far: Gratuitous use of generics, or any feature for that matter, without knowing the ramifications is never good. Whenever a fully constructed type is created, the runtime must generate that code within memory. Also, fully constructed types created from generic types with static fields will each get their own copy of the static fields. Moreover, they’ll all get their own version of the static constructor. So, if the generic contains a field like this:
<pre class="brush:csharp">
public class MyGeneric<T>
public static int staticField;
then MyGeneric<int>.staticField and MyGeneric<long>.staticField will both reference different storage locations.

The moral of the story is that you must consider the engineering trade-off. Although generics help avoid boxing and generally create more efficient code, they can also increase the size of your application’s working set. If in doubt, measure the results using performance-analysis tools to determine the proper route to take.

Even if your class derives from a class that uses virtual methods, it will be more efficient if you declare it sealed, because the compiler can then call those virtual methods nonvirtually when calling through a reference to the derived type.

Source Of Information : Apress Accelerated C Sharp 2010


Subscribe to Developer Techno ?
Enter your email address:

Delivered by FeedBurner