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