Oh, DBNull, how you complicate my code! You throw exceptions when I try to cast or convert you, forcing me to litter my code with conditionals that check for you first. Well, your days of plaguing my code with repetitive conditional expressions and operators are at an end, because I just wrote a new utility class that can cast an object to any type, returning a user-defined default value of that same type if the object is DBNull. And thanks to the power of C# 2.0 generics, it only took 7 lines of code. And 4 of those are curly braces.
On a more serious note, this article is really about the same thing as the last one I wrote: how to reduce or eliminate repetitive code. Today's inspiration came from the annoying stock behavior of the DBNull class, which actually goes to the trouble of implementing the IConvertable interface just so it can throw exceptions if any code tries to convert it. The result is that you end up writing a lot of code like this:
// Assume dr is a DataReader
object o = dr[ "Column1" ];
int i = ( o != DBNull.Value ) ? (int) o : 0; // or whatever default value makes sense
Code like this, while innocuous and relatively harmless, just kind of gets to a man after a while. I started to write a class that would test for DBNull before casting to a given type, and it looked kind of like this:
public static class CastDBNull
{
public static string ToString( object value, string defaultValue )
{
return ( value != DBNull.Value ) ? (string) value : defaultValue;
}
public static int ToInt32( object value, int defaultValue )
{
return ( value != DBNull.Value ) ? (int) value : defaultValue;
}
// And so on
}
It didn't take long to recognize a pattern: I was writing the same code over and over again, varying only the type. This calls for generics! The resulting code after applying generics to the problem becomes much more compact:
public static class CastDBNull
{
public static T To<T>( object value, T defaultValue )
{
return ( value != DBNull.Value ) ? (T) value : defaultValue;
}
}
The generic version takes a type specifier that determines both the return type and the type of the default value. In case generic syntax is still new and strange-looking to you, perhaps an example of how to use this class will help illustrate its power and flexibility:
// Pass string type to cast to string
string s = CastDBNull.To<string>( dr[ "Column1" ], String.Empty );
// Same class, same method, but passing int type allows casting to int
int i = CastDBNull.To<int>( dr[ "Column2" ], 0 );
Calls to this class take a little less typing than the conditional expressions and operators they encapsulate, but more importantly to my fingers, I find them easier to type. I find that writing lots of little utility classes like this makes programming both faster and more enjoyable. Thanks to a flexible method in the Convert class, the same kind of logic can be applied to convert values generically rather than simply casting them:
public static class ConvertDBNull
{
public static T To<T>( object value, T defaultValue )
{
if ( value == DBNull.Value ) return defaultValue;
return (T) Convert.ChangeType( value, typeof( T ) );
}
}
I hope that you've enjoyed today's submission. If you need training or consulting, contact us and get the Falafel team working for you!