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.

No comments:

Post a Comment