How can I fix this up to do generic conversion to Nullable<T>?
public static T To<T>(this IConvertible obj)
{
Type t = typeof(T);
Type u = Nullable.GetUnderlyingType(t);
if (u != null)
{
return (obj == null) ? default(T) : (T)Convert.ChangeType(obj, u);
}
else
{
return (T)Convert.ChangeType(obj, t);
}
}
public static T To<T>(this IConvertible obj)
{
Type t = typeof(T);
if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>))
t = t.GetGenericArguments()[0];
return (T)Convert.ChangeType(obj, t);
}
But if the conversion fail, it will throw an exception, not returning a null as should be expected.
I've ended up with this
private static T To<T>(this Object @object, Boolean returnDefaultOnException)
{
Type type = typeof(T);
Type underlyingTypeOfNullable = Nullable.GetUnderlyingType(type);
try
{
return (T) Convert.ChangeType(@object, underlyingTypeOfNullable ?? type);
}
catch (Exception exception)
{
if (returnDefaultOnException)
return default(T);
String typeName = type.Name;
if (underlyingTypeOfNullable != null)
typeName += " of " + underlyingTypeOfNullable.Name;
throw new InvalidCastException("Object can't be cast to " + typeName, exception);
}
}
public static T To<T>(this Object @object) { return @object.To<T>(returnDefaultOnException: false); }
public static T ToOrDefault<T>(this Object @object) { return @object.To<T>(returnDefaultOnException: true); }
It behaves like the LINQ extension methods Single
and SingleOrDefault
and First
and FirstOrDefault
.
In short, To<T>()
tries to convert and throws on failure while ToOrDefault<T>()
tries to convert and returns default(T)
on failure.