Friday, August 26, 2011

C# Arrays, extension methods and the way not to do something

Right let me first start of by saying, the problem that this code solves should never exist, and I mean NEVER! There is no good reason to have to do this unless you have a legacy system that has all of a sudden had the carpet pulled out from underneath it, you have to add new functionality and if you don’t get it done on time (which is the next three days) the world will end. Seriously though, avoid this at all costs if you possibly can.

Right that being said, I had a problem where by thousands of lines of code had been written against a SOAP service which made use of collections had been written many moons ago. Recently the definitions changed and all the collections were now arrays! The proxies are generated against svcutil and yes I know there is a switch to use collections as opposed to arrays but I entered the project at a time were it had been decided to convert all the code using the collections. Right this posed a significant problem in that myObject.Collection.Add() no longer existed.

My first thought (yes perhaps not one of my greatest moments) was to do this

//given 
myObject.Collection.Add(myNewItem);

//Convert it to
myObject.Array.ToList().Add(myNewItem);




Now for some reason this made sense in my head till I did it and found out it wasn’t working. Why wasn’t it working? You guessed it! The instance of ToList() was not being assigned to the collection. DOH!





Well my next solution was to implement a generic method that converted the array to a list, added the item then converted the list back to an array. Something like this.





   1: public class ArrayHelper{



   2:     public static void Add(ref T[] array, T input) {



   3:         if (array == null)



   4:             array = new T[0];



   5:     



   6:         var list = array.ToList();



   7:         list.Add(input);



   8:         array = list.ToArray();



   9:     }



  10: }



  11: //Usage would be



  12: ArrayHelper.Add(ref myObject.Array, myNewItem);




Well that looks a bit better and the best part? It works! Well kinda Sad smile When running performance tests on it it turned out that adding 5000 items to this array it would take 71 milliseconds as opposed to the 2 milliseconds to do it natively. What a bummer. Well back to the drawing board I guess. This means if it takes 0.0004 milliseconds to add one item natively it would take 0.015 milliseconds to add one time using this method. This equates to 37.5 times longer!



I then came across Array.Resize and figured I would see what that does. So the method became:





   1: //Class definition



   2: public static void Add(ref T[] array, T input){



   3:     if(array == null)



   4:         array = new T[0];



   5:



   6:         Array.Resize(ref array, array.Length + 1);



   7:         array[array.Length - 1] = input;



   8: }



   9: //Usage remains the same




This method took 10 times longer to add 5000 items. This means it would take 0.004 milliseconds to add one item. A bit more acceptable. Now thinking I am the cheese I wanted to wrap this into an extension method. My first attempt failed so I started looking around if anyone else had done this. Seems someone had http://these-pretzels-are-making-me-thlrsty.blogspot.com/2010/05/c-extension-method-bummer.html and verified what I was too scared to admit, it wasn’t going to happen as an extension! Again this is an elegant solution to a problem that should never have existed.





Oh well …





References:





//given

myObject.Collection.Add(myNewItem);



//Convert it to

myObject.Array.ToList().Add(myNewItem);



    No comments:

    Post a Comment