Code Snippet: ConvertToTypeT
I live for nifty code snippets. They make life so much easier. I also like .NET's generics support. When I was recently writing a utility library for myself, I found myself wanting to convert command line arguments to a defined type. How would one go about converting an arbitrary argument passed as a string to an application specific typed value? Turns out it is extremely simple, if you use the wonderful world of generics!
You may be familiar with the Convert
static class in .NET. To perform our trick, we're going to use Convert.ChangeType(object, Type)
to convert a generic type of T
to a given type, determined by the caller of the method.
/// Converts an to a type.
/// Generic type parameter.
/// The object.
/// The given data converted to a type
private static T ConvertToTypeT(object obj) where T : IConvertible
{
var t = Convert.ChangeType(obj, typeof(T));
if (t != null)
{
return (T)t;
}
return default(T);
}
Of particular interest in this code is the constraint that we put on the generic type T
. We restrict T to types that implement the IConvertible
. This will allow us to pass a generic object obj
into our method, defining T
as a specific type, and allows the Convert
class to convert it to an object that boxes the typed value. All we do then is cast the value as a type T
.
In the case of an invalid conversion type, we can't return null because we need to return a generic type T
. T
may be a nullable type, but it may also be a non-nullable primitive type. For that reason, we need to return the default value of T by calling the .NET method default(T)
, which returns null for nullable types, or the default value defined for a primitive data type.
Let's use our conversion method.
public static void DoSomething()
{
string argument = Environment.GetCommandLineArgs().First();
int intValue = ConvertToTypeT(argument);
//We can convert to an integer.
bool boolValue = ConvertToTypeT(argument);
//We can convert to an boolean value.
string stringValue = ConvertToTypeT(argument);
//Remember this takes a generic object, so strings work as well.
}
Note: Thanks to some constructive feedback, I've made two updates. I updated the declaration of t
so that no casting occurs. Instead, we check that Convert.Change(obj, typeof(T))
gave us something other than null, as it returns an object
. If not null, we then cast t
as a T
, otherwise return the default value of T
.