What a tangled web I weaved

time to read 17 min | 3201 words

I think that for some reason, the bozo bit alarm malfunctioned today. Check this out:

public static class FormatterWiseAss

{

    static IDictionary<Type, Converter<object, string>> formatters = CreateFormatters();

 

    public static IDictionary<Type, Converter<object, string>> CreateFormatters()

    {

        Dictionary<Type, Converter<object, string>> dic = new Dictionary<Type, Converter<object, string>>(new TypeComparer() );

        dic.Add(typeof(Foo), delegate(object obj) { return ((Foo)obj).FooName; });

        dic.Add(typeof(Bar), delegate(object obj) { return ((Bar)obj).BarName; });

 

        //several more like it.

        return dic;

    }

 

    public static string Format(object obj)

    {

        Type type = obj.GetType();

        return formatters[type](obj);

    }

 

    public class TypeComparer : IEqualityComparer<Type>

    {

        public bool Equals(Type x, Type y)

        {

            return x.IsAssignableFrom(y);

        }

 

        public int GetHashCode(Type type)

        {

            return type.GetHashCode();

        }

    }

}

This "masterpiece" takes an object, and turn it into a string representation based on a delegate keyed to the object's type (or parent type). The examples here are very simple, but it is usually traversing some object graph to find the correct answer. This monster is actually needed to handle formatting for untyped objects, where I do not know at compile time what the type of the object is.

I made an architectual change today that meant that I was working with typed objects. It was only when I needed to add a new formatting object that I realized what happened here. I replaced it with this:

public static class FormatterSimple

{

    public static string FormatFoo(Foo foo)

    {

        return foo.FooName;

    }

 

    public static string FormatBar(Bar bar)

    {

        return bar.BarName;

    }

}

One of the best things that I can do to a project is to reduce the amount of code in it. Thinking about it, there is an obscure feature called overloading that I don't know if you heard about, it allows me to write the code like this:

public static class FormatterNice
{

    public static string Format(Foo foo)

    {

        return foo.FooName;

    }

 

    public static string Format(Bar bar)

    {

        return bar.BarName;

    }

}

This is even source code compatible with the first version, and it has the advantage that I actually don't need to think to realize what is going on here. In this example the line count went from 15 to 5, and the complexity from fairly large to nothing. I am genuinely fond of the delegate dictionary method, and it is quite handle in several situations, but I am very glad that I can get rid of it.