Friday 20 May 2011

Checking for null in generic methods

My OptionType<T> class indicates whether the underlying reference type is null or not whilst retaining all the good type information and forcing the hand of the developer to think about checking for null, at the very least (unfortunately the C# compiler won't let me force the check :-( ). But this didn't work very well for string types because string.Empty is also considered as a null value in many circles, including this one, hence the prevalence of string.IsNullOrEmpty checks all over our codebase.

Now the problem arose when I had an OptionType<string> which was used to represent string.Empty. The simple check I had in place was nothing more than an equality check with null which was clearly unsatisfactory here. What I needed was to check using string.IsNullOrEmpty, but only when T is a string.

The obvious way to approach this would be to abstract out the null checking behaviour, not into a separate parameter because that would be nasty but into a set of functions from which the compiler would make the appropriate selection. Mind you, non-generic calling code worked just fine! Typical!

And so I introduced


public static class Check
{
public static bool IsNull(string s)
{
return string.IsNullOrEmpty(s);
}

public static bool IsNotNull(string s)
{
return !IsNull(s);
}

public static bool IsNull(T t) where T : class
{
return t == null;
}

public static bool IsNotNull(T t) where T : class
{
return !IsNull(t);
}
}


To my dismay, however, the call to Check always selected the generic method, even when the generic type was actually a string. Argh! And so we end up with


public static class Check
{
public static bool IsNull(string s)
{
return string.IsNullOrEmpty(s);
}

public static bool IsNotNull(string s)
{
return !IsNull(s);
}

public static bool IsNull(T t) where T : class
{
return t == null;
}

public static bool IsNotNull(T t) where T : class
{
return !IsNull(t);
}

// We need these two because OptionType cannot call IsNull(string), it can only call IsNull(string)
public static bool IsNullString(string s)
{
return IsNull(s);
}
public static bool IsNotNullString(string s)
{
return IsNotNull(s);
}
}


which is called from the OptionType constructor in the following manner:


if ((typeof(T) == typeof(string) && Check.IsNotNullString(t as string)) || (typeof(T) != typeof(string) && Check.IsNotNull(t)))
{
_t = t;
_isEmpty = false;
}


Not pretty, but it does work. Let me know if you come up with a neater way to achieve this.

Wednesday 18 May 2011

Null values in dictionaries

Eeek! Why on Earth would someone insert null values into a dictionary? Especially when one sees code like


Dictionary<A,B> d = new Dictionary<A,B>();


blah


TryGetValue( key, out value);
if(value==null) throw new Exception();


That is to say that the return value from TryGetValue is routinely ignored and instead the null-ness of the output value is used to indicate failure. Clearly this has been written because the original author didn't want to wrap dictionary access in try ... catch(), which is understandable, but ...

So I propose that null indicates failure. With this in mind, we can rewrite TryGetValue as follows:


public static Nullable<V> TryGetValue(Dictionary<K,V> d, K key)
{
V v;
bool s = d.TryGetValue(key, out v);
return s ? v : (Nullable<V>)null;
}


This is, of course, absolutely spiffing because now TryGetValue is a function which returns the sought value and so lends itself to a declarative programming style.

Also, with the parameters in the order key then dictionary we allow ourselves the possibility of function pipelining.

Monday 9 May 2011

Overriding the database access in CSMApi

Sophis' CSMApi class provides the method GetDBAccess(CMString). At first blush this is not going to help because the CMString is passed in and not out of the method. However, the CMString is a tricky class, and it has the method SetString() which allows you to change the underlying string representation even if the object itself has all the appearances of being constant, or at least non-modifiable. Another good reason to avoid CMString.

Anyway, the upshot is that you can override GetDBAccess to provide your own connection details. Interestingly, it turns out that if your CSMApi derivative is in the exe this all works fine but if it is in a dll then, oh dear, it doesn't work. I don't know why at this point, but I assume that there are statics in CSMApi which have some evil order-dependencies...

I'll let you know if I find out what's going on.