Casting to nullable generics

Hi.

I have this method:

public static TVal DoIT<TVal>(object value)
{
return (TVal)Convert.ChangeType(value, typeof(TVal));
}

But it fails in case of DoIt<DateTime >(DateTime.Now). (Invalid cast from 'System.DateTime' to 'System.Nullable`1[[System.DateTime, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'.)

How can I make it working

I was trying to catch that case myself (happy with typeof(TVal).IsNullable), but I'm not able to create required nullable type because no constructor I found takes a System.Type (which I can get using Nullable.GetUnderlyingType)...



Answer this question

Casting to nullable generics

  • yogiberr

    Dear miloush,

    change into "DoIt<DateTime>(DateTime.Now);"



  • Sumith Koshy

    there is no constructor with nullable type.

  • Zulfiqar Taj

    Yes, I agree, that's fine. The problem is with values, which are not null.

    So the question (from my point of view) is, how can I create an instance of Nullable type with the Type specified


  • Hemanth C Murthy

    You know, it may or may not be as readable, but if you know the type of value you're trying to get out of the DataRow, you can always use the "as" operator.

    However, if for whatever reason the value doesn't match the type you're casitng to you get null. This could be a problem if you're targeting multiple database platforms, but otherwise I rarely have trouble with it. When using a DataReader, however, I like to have a wrapper class that has methods returning nullable values instead.


    // nullables
    DateTime updateDate = dataRow["UpdateDate"] as DateTime ;
    int contactId = dataRow["ContactId"] as int ;
    // non-nullables
    bool flagged = dataRow["Flagged"] as bool false;

  • Surreal

    Unfortunately I'm using the DataReader. But thanks for the tip with DataRow.
  • alien3d

    While you cannot do it directly, you can always do what Comparer<T>.Default does and create specialized classes based on T and use Reflection to bypass the constraints (the compiler could admitedly be better here and provide a syntax for "casting" in constraints, but it's not that big of a deal).

    Anyway, what I mean to say is you can do it this way (You may want to add more specializing and possibly checks for DBNull and whatnot, but this does what you were trying to do):

    namespace Example {
    using System;

    internal class ValueConverter<T> {
    internal static readonly ValueConverter<T> Instance = Initialize();
    private static ValueConverter<T> Initialize() {
    Type type = typeof(T);
    Type underlyingType = Nullable.GetUnderlyingType(type);

    if(underlyingType != null) {
    // if T is nullable, use reflection to create an instance of NullableValueConverter
    Type converterType = typeof(NullableValueConverter<>);
    converterType = converterType.MakeGenericType(underlyingType);
    return (ValueConverter<T>)Activator.CreateInstance(converterType);
    }
    else {
    // otherwise use a normal converter
    return new ValueConverter<T>();
    }
    }
    internal ValueConverter() { }
    internal virtual T ConvertValue(object value) {
    return (T)Convert.ChangeType(value, typeof(T));
    }
    }
    internal class NullableValueConverter<T> : ValueConverter<T > where T : struct {
    public NullableValueConverter() : base() { }
    internal override T ConvertValue(object value) {
    if(value == null)
    return null;
    return (T)Convert.ChangeType(value, typeof(T));
    }
    }

    class Program {

    public static T ConvertValue<T>(object value) {
    return ValueConverter<T>.Instance.ConvertValue(value);
    }

    static void Main(string[] args) {
    Console.WriteLine(ConvertValue<DateTime >(null));
    Console.WriteLine(ConvertValue<DateTime >(DateTime.Now));
    Console.WriteLine(ConvertValue<DateTime >(DateTime.Now.ToString()));
    Console.WriteLine(ConvertValue<DateTime>(DateTime.Now.ToString()));
    }
    }
    }


  • MayaMan

    Hi,

    thanks for the code, I've looked into it, but I need to handle NULLs because I'm casting to nullable types.

    The DataReader that will do well with nullable types can be written that way of course, but this is a little off-topic, since the problem I'm presenting here is (as it seems to me) that the nullable types does not have constructors.


  • Louis Lafreniere

    Nope.

    The thing is, that if value is null, it should return null.


  • Ebbe

    Hi.. thank you, very nice example...

    but I think I would stay at my frequently called helper function

    public static TVal FromDB<TVal>(object value)
    {
    TVal r =
    default(TVal);
    if (value != DBNull.Value)
    {
    r = (TVal)
    Convert.ChangeType(value, typeof(TVal));
    }
    return r;
    }

    and check for the DBNull.Value explicitly myself without that function, when casting tu nullable type.

    Please go ahead and vote for http://lab.msdn.microsoft.com/ProductFeedback/viewfeedback.aspx feedbackid=1af9f75d-e566-41ff-ae00-84729ef8469e !


  • Svend Tofte

    you can use nullable<T>,but this only supports struct.

  • JHPE

    Hello

    If you have problems with a Datareaders you should take a look at the "safeDatareader" from CSLA from Rocky Lhotka. Its a Datareader that will avoid all the NULL hassle you get if you know that you dont have to really care about NULLs. It is included in its CSLA code which you can download from its website... The datareader works exactly like a normal one with the only difference that it handels NULLs transperently. Also it supports the full datareader interface so it can be used exactly like the normal one... And while we are at the topic of NULL in DBs and .NET you should also look at the smartdate class

    Take a look at this site

    http://www.lhotka.net/

    Hope this helps...

    P.s. If you NEED to handle NULLs then just use the "plain" datareader



  • Sangeetha Edward

    then you should try to check if the value is null.

    because Convert.ChangeType(Object, Type) this method does not support null to pass in.

    MSDN:

    Parameters

    value

    An Object that implements the IConvertible interface.

    conversionType
    A Type.


  • Felix A

    Yes, I need Nullable<T> but with T taken form the generic, which is not supported as far as I have seen.

    So this cannot be solved in C# 2 I cannot convert a struct into its nullable representation without knowing the struct at design time


  • Casting to nullable generics