Convert.ChangeType doesn't handle nullables
I had an assembly, originally written against .NET 1.1 and now running
on .NET 2.0, that tried to convert a boxed DateTime object to a
Nullable<DateTime> (DateTime?) object, using the
Convert.ChangeType method. When this code runs, I get this exception:
[InvalidCastException:
Invalid cast from 'System.DateTime' to '
System.Nullable`1[[System.DateTime, mscorlib, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089]]'.]
System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider) +864
System.DateTime.System.IConvertible.ToType(Type type, IFormatProvider provider) +36
System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider) +433
System.Convert.ChangeType(Object value, Type conversionType) +38
Since a DateTime can be assigned to a nullable DateTime, it didn't make sense to me why it
couldn't be converted to one, by calling
Convert.ChangeType(Object, Type) with a Nullable as the second parameter. A
Google search showed that
Paul Wilson,
Cameron Beccario, and others ran into this too during the beta timeframe.
The CLR team at Microsoft confirmed that this is a known problem:
Yes,
Convert is not very extensible and was designed around a fixed set of
types to address a specific functionality requirement for VB.
System.ComponentModel has a more comprehensive data type conversion
model, and I believe does deal with nullable.
The docs showed a lot of System.ComponentModel classes for conversion, e.g.
DecimalConverter,
but unfortunately I couldn't use those in this particular case, since
it doesn't support the late-bound casting that code was doing. It was
disappointing that this particular case wasn't handled, but it's
probably a rare case, and it's understandable given some of the
changes to nullables that came so late in the game.
My workaround in the short term was to not use the Nullable type for
that particular method, until I could dig into System.ComponentModel
more to find an alternative, or a patch is released for
Convert.ChangeType to handle nullables.
Edit: I've now
implemented a wrapper that handles nullables correctly.