如何将字符串转换为在运行时确定的可为空类型?

The*_*ght 16 c# asp.net generics datetime nullable

我有下面的代码,我需要将一个字符串转换为一个也从String指定的类型:

 Type t = Type.GetType("System.Nullable`1[[System.DateTime, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]");

            object d = Convert.ChangeType("2012-02-23 10:00:00", t);
Run Code Online (Sandbox Code Playgroud)

我得到以下错误消息:

Invalid cast from 'System.String' to 'System.Nullable`1[[System.DateTime, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'.
Run Code Online (Sandbox Code Playgroud)

怎么会很好的可能?

我知道一种丑陋的方法是使用if来检查类型是否可以为空:

    Type possiblyNullableType = Type.GetType("System.Nullable`1[[System.DateTime, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]");

    var underlyingType = Nullable.GetUnderlyingType(possiblyNullableType);

    Object result;

    // if it's null, it means it wasn't nullable
    if (underlyingType != null)
    {
        result = Convert.ChangeType("2012-02-23 10:00:00", underlyingType);
    }
Run Code Online (Sandbox Code Playgroud)

会有更好的方法吗?

谢谢,

小智 30

有两个问题.

首先,Convert.ChangeTypejust plain不支持可空类型.

其次,即使它确实如此,通过装箱结果(将其分配给a object),你已经将它转换成了一个DateTime.

您可以使用特殊情况可为空的类型:

string s = "2012-02-23 10:00:00";
Type t = Type.GetType("System.Nullable`1[[System.DateTime, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]");
object d;

if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>))
{
    if (String.IsNullOrEmpty(s))
        d = null;
    else
        d = Convert.ChangeType(s, t.GetGenericArguments()[0]);
}
else
{
    d = Convert.ChangeType(s, t);
}
Run Code Online (Sandbox Code Playgroud)

  • @William`GetGenericTypeDefinition()`如果类型不是通用的,则抛出异常. (2认同)

The*_*ght 10

我编写了以下通用助手方法,该方法适用于大多数场景(未使用泛型类型进行测试):

static void Main(string[] args)
{
    Object result =
        ConvertValue(
            "System.Nullable`1[[System.DateTime, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]",
            "2012-02-23 10:00:00");
}

public static Object ConvertValue(string typeInString, string value)
{
    Type originalType = Type.GetType(typeInString);

    var underlyingType = Nullable.GetUnderlyingType(originalType);

    // if underlyingType has null value, it means the original type wasn't nullable
    object instance = Convert.ChangeType(value, underlyingType ?? originalType);

    return instance;
}
Run Code Online (Sandbox Code Playgroud)