Click here to Skip to main content
15,888,977 members
Articles / Programming Languages / C# 4.0

A non-generic IList implementation without any Boxing and Unboxing

Rate me:
Please Sign up or sign in to vote.
2.00/5 (4 votes)
18 May 2009CPOL2 min read 32.3K   8   10
A simple workaround to avoid boxing and unboxing while still using a non-generic IList implementation

UPDATE (May 18, 2009): The title of this article has created some confusion for fellow CodeProject members, the explanation of which is that my intention was NOT to avoid .NET generics completely but, to present an implementation of "non-generic System.Collections.IList interface" without boxing and unboxing. 

While writing this post, I'm assuming that you know what boxing/unboxing means in the .NET context and in case you don't, read this MSDN article to know more about it.

In the default implementation of IList interface such as ArrayList, when you Add() a ValueType item to the list, the value is boxed inside a Object. Similarly, when a ValueType element is retrieved from the list, unboxing occurs and explicit casting must be performed.

Now, according to MSDN documentation, it can take upto 20 times longer than a simple reference assignment and the casting takes upto four times long as an assignment.

Provided below is my own implementation that gets rid of boxing/unboxing problem while still using the same old fashioned non-generic IList:

C#
class VariantList : VariantListBase
{
  #region Methods
  public int Append<T>(T value) where T : struct {
    return (this as IList).Add(new T[1] { value });
  }

  public T GetAt<T>(int index) where T : struct {
    T[] value = (T[])(this[index]);
    return value[0];
  }
  #endregion
}

VariantListBase is an abstract class implementing IList with a structure similar to the following:

C#
abstract class VariantListBase : System.Collections.IList
{
  private System.Collections.IList innerList = new System.Collections.ArrayList();

  /*********
   * IList, ICollection and IEnumerable method implementations
   * simply forward the call to this.innerList
   *********/
}

So, how does VariantList avoid boxing/unboxing? It achieves this by using arrays.

Remember that any type of array derives from System.Array base class, which itself, is a reference type. And this is exactly what is being done in the Append<T>(T value) method. When Append<T>() is used to add a ValueType element to the list, a new array of one single element of the same type T is created and added, thus completely avoiding the need for boxing. In the same way, when a value is retrieved using GetAt<T>(int index) method, it is retrieved without performing any unboxing process.

But here is the deal: After performing the 10 million iteration benchmarking and using Hi-Res Timer, I haven't found much difference (only a few milliseconds) between the time taken to insert as well as retrieve items using ArrayList and VariantList. And I'll be honest with you, while repeating benchmarks, a few times VariantList actually performed a little slower than the ArrayList.

Anyways, if you want to use this code, perform some benchmarks and see if it's of any advantage to you. Also, if you have any comments, suggestions, criticisms, etc. on this article, please feel free to share.

This article was originally posted at http://feeds2.feedburner.com/gskBlog

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 1 Pin
zecanard23-Nov-09 9:41
zecanard23-Nov-09 9:41 
GeneralI gave it 5. Pin
f_numb3r20-May-09 7:51
f_numb3r20-May-09 7:51 
GeneralRe: I gave it 5. Pin
gUrM33T20-May-09 12:35
gUrM33T20-May-09 12:35 
GeneralMy vote of 1 Pin
Wesner Moise19-May-09 11:47
Wesner Moise19-May-09 11:47 
GeneralRe: My vote of 1 Pin
gUrM33T19-May-09 12:26
gUrM33T19-May-09 12:26 
GeneralProblems Pin
Wesner Moise19-May-09 11:37
Wesner Moise19-May-09 11:37 
QuestionReally better? Pin
peterchen18-May-09 3:45
peterchen18-May-09 3:45 
GeneralMy vote of 1 Pin
haindl17-May-09 22:05
haindl17-May-09 22:05 
GeneralInteresting, but... Pin
User 304249817-May-09 12:51
User 304249817-May-09 12:51 
GeneralRe: Interesting, but... Pin
gUrM33T18-May-09 12:32
gUrM33T18-May-09 12:32 
Joe Enos wrote:
It's an interesting concept - it does avoid boxing and unboxing, but what is the benefit if it doesn't provide a performance gain?

When I started looking for a solution that can avoid Boxing and Unboxing, I was not looking for any performance gain benefits but was only interested in finding a workaround with which I can accomplish what I wanted. Even at the end of the article, you'll find that I've given the results of my benchmarks and said that VariantList class actually sometimes performs slower than ArrayList. As MSDN documentation tells you about the performance loss associated with boxing and unboxing, I just wanted to see if there exist an option to avoid it completely (even without performance benefits).

Joe Enos wrote:
I'd expect that the creation of an array object with each insertion is the reason it doesn't perform well. I don't know for sure, but I would think that creating an object of type int[] is close to the same performance as boxing an int into an object in the first place.

That is exactly what I think the reason is.

Joe Enos wrote:
You might have better luck with a custom class that acts as a container for the value, rather than an Array, since an Array has quite a bit of overhead with it - would accomplish the same thing.

Yes, it does performs better than arrays but then again, not better than the default ArrayList or IList<object>.

Joe Enos wrote:
Also, you said your goal was a non-generic class, which you have, but since the methods are generic, what have you really accomplished? You won't be able to use this class in .NET 1.x code or anywhere else where generics aren't allowed.

Oops! That's my bad, the article title should have been "An IList implementation without Boxing and Unboxing".

Joe Enos wrote:
You've really got a collection that accepts any object, as long as it's a value-type.

Actually that's not true; it accepts both reference and value types. Moreover, I myself have come across scenario where you don't know the type going in the list beforehand i.e. when you want to allow both references and values.

Joe Enos wrote:
what have you really accomplished?

What I've accomplished is that now I'm sure that boxing and unboxing doesn't make that big a difference performance wise (atleast in general .NET applications)

I really appreciate all your comments. Thanks Smile | :)

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.