I am creating a generic converter
Here is a sample code of the generic converter
bool TryReaderParse<TType>(object data, out TType value)
{
value = default(TType);
Type returnType = typeof(TType);
object tmpValue = null;
if (returnType == typeof(DateTime))
{
tmpValue = StringToDatetime(data.ToString());
}
else if (returnType == typeof(DateTime?)) // THIS IF FIRES
{
tmpValue = StringToNullableDatetime(data.ToString());
}
value = (TType)Convert.ChangeType(tmpValue, returnType); // THROWS
}
public DateTime? StringToNullableDatetime(string date)
{
DateTime? datetime = null;
if (!string.IsNullOrEmpty(date))
{
datetime = DateTime.Parse(date, new CultureInfo(Resources.CurrentCulture));
}
return datetime;
}
And this is how I use it:
void foo()
{
DateTime? date = null;
TryReaderParse<DateTime?>("25/12/2012", out date);
}
The thrown exception says that it cannot convert from DateTime
to Nullable<DateTime>
. Since, the method creates and returns a nullable type, how come the casting fails?
At the end, I want to have a nullable DateTime, in this particular example.
edit The problem is that StringToNullableDatetime
method returns a Datetime?
and the casting says that cannot convert from Datetime
Since the StringToNullableDatetime
method returns a nullable datetime, how is it possible that the Convert.ChangeType
cannot see that the passed argument is nullable?
Ps. I've read answers like this one that do the opposite (casting from nullable).
The thrown exception says that it cannot convert from
DateTime
toNullable<DateTime>
. Since, the method creates and returns a nullable type, how come the casting fails?
Good question. This fails because there is no such thing as a boxed nullable. When you convert a DateTime?
to object
, you either get a null reference, if the DateTime?
was null, or you get the boxed value, a DateTime
. You never get a boxed nullable struct; there is no such thing.
Therefore you end up with either null, or a valid DateTime in that box. You then tell Convert to convert that to a nullable DateTime, and Convert does not know how to do that.
My advice is that you abandon this line of attack entirely; this code is borderline abusive of generics. Any time you make a switch on the specific type of a generic, your code is no longer generic and you are probably doing it wrong. If you want to do a "try"-style method for datetimes then just write that:
DateTime? TryReadDateTime(object data)
{
... return null if the object cannot be read as a datetime ...
}
Write such a method for every type that you intend to read. The user would much rather write:
DateTime? d = TryReadDateTime(data);
if (d != null) ...
Than
DateTime d;
bool b = TryRead<DateTime>(data, out d);
if (b) ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With