Friday, 2 January 2009

IEnumerable Extension Methods

After looking over some questions on StackOverflow it got me thinking about extension methods. It's not really something which I have looked into much as I only use Visual Studio 2008 at home for personal projects. I stumbled upon one post about potential extension methods to add to a colaboration on CodePlex for everyones use. I was scrolling through some of the potentials to be submitted and came across this post. It intrigued me as the main method was converting an IEnumerable to a string with a separator ... so would convert an array of ints 1,2,3 into the string "1, 2, 3" if the separator was ", " ... I think you get the point.

However the way they were doing it was the usual "go through all the items, add the separator after everyone, then at the end take the last off". Personally when I see this I get a little sad. It's just not very elegant but also it means you don't harness the power of the framework ... which is what it is there for!

Side Note With the advent of .net 2.0 Generics was brought in. This opened up a whole world of fun for developers and a lot of useful things especially around the area of collections. If you've not looked at Generics I would highly recommend working your Google-Fu and doing some reading.

Anyway ... using generics I decided to refactor the ToString method for IEnumerable to use ToArray() of a List and string.join(). This might be a new way for some people of concatenating values together with a supplied separator. It leverages the power of the .net framework to do the work and avoids having to add an extra separator and then removing it once you have iterated through all the items in the list and performing the specified delegate function.

        public static string ToString<T>(this IEnumerable<T> collection,
Func<T, string> stringElement, string separator)
        {
            List<string> result = new List<string>();
            foreach (T item in collection)
            {
                result.Add(stringElement(item));
            }
            return string.Join(separator, result.ToArray());
        }


So moving on from this I thought that a List has a ForEach extension method which executes a delegate on each of the elements in the list; but not on an IEnumerable. This has been discussed and documented in so many places I'm not going to write about it here.  So what I wanted to do was break out the ForEach functionality out of the ToString implementation so it can be used injunction with it, but also by itself.


        public static IEnumerable<T> ExecuteForEach<T>(this IEnumerable<T> collection,
Func<T, T> function)
        {
            List<T> result = new List<T>();
            foreach (T item in collection)
            {
                result.Add(function(item));
            }
            return result.AsEnumerable();
        }


I made it return an IEnumerable<T> so it could be piped together to keep with the design of linq and lambda expressions etc. The limitation of this implementation is that it returns the same type as the type passed into the Func so you can't change the type, such as converting int to string. So take two came along ...


        public static IEnumerable<U> ExecuteForEach<T, U>(this IEnumerable<T> collection,
Func<T, U> function)
        {
            List<U> result = new List<U>();
            foreach (T item in collection)
            {
                result.Add(function(item));
            }
            return result.AsEnumerable();
        }


Same as the previous example, but with two different generic types, this enables the conversion of int to string, but also performing actions on the same types and returning the updated values eg. increment a list of ints.

With using the updated ExecuteForEach<T, U> (I decided on calling it ExecuteForEach as it will update / perform a function on each of the items in the collection and update them, not just perform an function on them) we can now update the ToString method call to be just two lines;  it abstracts the looping away into a different function which can be used again for different actions, but also uses the power of the framework with the string.join functionality.


        public static string ToString<T>(this IEnumerable<T> collection,
Func<T, string> stringElement, string separator)
        {
            List<string> possible = collection
.ExecuteForEach(t => stringElement(t))
.ToList();
            
            return string.Join(separator, possible.ToArray());
        }


A simple usage of this is ...


        public static string ToString<T>(this IEnumerable<T> collection, string separator)
        {
            return ToString(collection, t => t.ToString(), separator);
        }


... and the unit test to go with it ...


        [TestMethod]
        public void ToStringTest()
        {
            var ints = new int[] { 1, 2, 3 };
            var result = ints.ToString(", ");
            Assert.AreEqual("1, 2, 3", result);
        }


Hope this all makes sense, please let me know if you have any comments or thoughts about this :-)

Windows Live Writer

Well I've finally taken the plunge and found the MSI installer so that Windows Live Writer installs on my windows 2003 server dev virtual machine. This way I can write my posts offline while I'm on the train and hopefully have better control of the layout especially as I'm in the middle of a couple of posts which have code in it and formatting that via the web interface I'm finding tricky so will see how this goes.

Thursday, 25 December 2008

Happy Christmas!!

Happy Christmas!!! :-)

Wednesday, 24 December 2008

Rediculous Error Message

I'm getting a bit sick with writing posts on the train and then copy 'n' pasting them into the web interface on blogger and then having to faff around with the formatting, so I thought I would download Windows Live Writer and see how that pans out. I've heard some good things and I've heard some bad things, but I'm willing to give it a go.

However, when I was downloading the installer and trying to install the thing it runs through the download routine and then checks for other Live programs running ... I don't know why, but it does ... if it goes on for a long time and the progress bar gets to the end and starts again the error message changes into something rediculous ...


Also, I've managed to write this post and upload the image in the time its taken to fill up that progress bar ...

... just checked it ... its started again! I give up!

I guess I'm staying with the web interface for now :-(

Tuesday, 23 December 2008

Exercise Week #8 & #9

The past few weeks have been very manic at work and I have not been able to find time to update this as often as I usually do. This is partially down to Christmas parties, but also due to the increased pressure at work to get a certain project through the UAT criteria which is pretty tight. I didn't have to go in at the weekend (20/21) but a lot of the chaps did and worked really hard. I think we're all looking forward to some time off over Christmas to see the families and recover ... ready for the new year.

Bad time for the beer ratio, really need to try harder over the festive period and on into next year :-)

Week #8
Monday - 1 gym visit
Tuesday - rest
Wednesday - Working late
Thursday - rest
Friday - Work Christmas Party
Saturday - Recovery
Sunday - rest

Week #9
Monday - 1 gym visit
Tuesday - rest
Wednesday - Feeling rough
Thursday - Off work ill
Friday - Lau's Work Christmas Party
Saturday - resting (recovery and due to lack of sleep due to Lau's coughing keeping me awake)
Sunday - 1 gym visit + 10 lengths swim (b,2f,b)


Week #8 Beers
Wednesday - 1 beer
Friday - 6 beers (Christmas Party)

Week #9 Beers
Thursday - 2 beers (Medicine wasn't working)
Friday - 6 beers (Burger Friday & Christmas Party)
Sunday - 2 beers (Parents after Carol service)


Current Status : Bad!

Beers: 131
Miles: 33
DG Rounds: 19
Gym visits: 16
Lengths : 40 (week: 10; total: 400)

Key
Good => Exercise > Beers
Level => Exercise == Beers
Bad => Exercise < Beers