Saturday, May 29, 2010

C# Extension Method Bummer

I love extension methods, which were introduced in .NET 3.5 Framework.  While trying to avoid extending everything and its grandmother, I find them very useful for very common tasks like special ToString() formatting or basic array manipulation (adding an element to an already full array).  But I was pretty disappointed to find an ugly limitation of extension methods, specifically in C#.

Let's say for example you want to create an extension method that adds an item to an array of objects while dynamically growing said array.  Note:  Sure we can do these things easily with ArrayLists or any other type of generic lists.  But say you're stuck with working with simple arrays... just go with me here.

So consider the following extension method:
public static void Add<T>(this T[] source, T newItem)
{
    // Create a new temporary array that's larger than the original
    T[] tmp = new T[source.Length + 1];

    // Copy contents of source array to temporary array
    source.CopyTo(tmp, 0);

    // Assign new item to the temporary array
    tmp[tmp.Length] = newItem;

    // Set original source to the newly grown array
    source = tmp;
}
And then you can simply add an item to an array with a single line of code:
user[] users = new user[0];
users.Add(new user());

Wouldn't it be nice if it were that simple?   ...and working?  Unfortunately, that is not the case with C#.  Remember that in C# objects are passed by value, not reference.  So the fact that we're setting source to tmp at the end of the extension method bares no impact whatsoever on the original source array outside of this method's scope.  This is one of those very rare times I say, "What the hell?!  I'd be better off doing this in VB!"

You also can't use ref keyword to pass this instance into the extension method by reference, because you're not really supplying that parameter to the method when calling it.  So there's nothing to put ref in front of.

So one alternative is to just return the new array:
public static T[] Add<T>(this T[] source, T newItem)
{
    // Create a new temporary array that's larger than the original
    T[] tmp = new T[source.Length + 1];

    // Copy contents of source array to temporary array
    source.CopyTo(tmp, 0);

    // Assign new item to the temporary array
    tmp[tmp.Length] = newItem;

    // Return the newly grown array
    return tmp;
}

But that's ugly, because now you have to assign the return value to the variable you just called a method on:
user[] users = new user[0];
users = users.Add(new user());

And that just gives me the willies.  It gets the job done, but... ugh..   I sure would have preferred to be able to alter the original object within the extension method - that way seems a lot cleaner to me.  What a bummer!

Friday, May 21, 2010

Thursday, May 6, 2010

Image Map Generator

Here's an excellent tool that helps you create an image map with hotspots/links:  http://www.image-maps.com/ - Online Image Mapper.

Just upload your image or specify its URL and start creating your areas:

You'll be provided with standard HTML-style image map code, as well as a CSS-only version of the code.