在泛型方法中无法将类型更改为可为空

Ody*_*dys 5 c# generics casting nullable .net-3.5

我正在创建一个通用的转换器

以下是通用转换器的示例代码

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;
}
Run Code Online (Sandbox Code Playgroud)

这就是我使用它的方式:

void foo()
{
    DateTime? date = null;
    TryReaderParse<DateTime?>("25/12/2012", out date);
}
Run Code Online (Sandbox Code Playgroud)

抛出的异常表示它无法转换DateTimeNullable<DateTime>.既然,该方法创建并返回一个可空类型,那么转换怎么会失败呢?

最后,我希望在这个特定的例子中有一个可以为空的DateTime.

编辑问题是该StringToNullableDatetime方法返回一个Datetime?并且该转换表示无法转换Datetime

由于该StringToNullableDatetime方法返回一个可为空的日期时间,如何Convert.ChangeType才能看到传递的参数可以为空?

PS.我已经阅读过像这样的答案(从可空中铸造).

Eri*_*ert 18

抛出的异常表示它无法转换DateTimeNullable<DateTime>.既然,该方法创建并返回一个可空类型,那么转换怎么会失败呢?

好问题.这失败了,因为没有盒装可空的东西.当你转换DateTime?object,你要么得到一个空引用,如果DateTime?是null,或者你得到盒装,a DateTime.你永远不会得到一个盒装的可空结构; 哪有这回事.

因此,您最终会在该框中使用null或有效的DateTime.然后告诉Convert将其转换为可以为空的DateTime,并且Convert不知道如何做到这一点.

我的建议是你完全抛弃这一攻击线 ; 这段代码是泛滥的泛型.每当你切换特定类型的泛型时,你的代码就不再是通用的,你可能做错了.如果你想为日期时间做一个"尝试"式方法,那么只需写下:

DateTime? TryReadDateTime(object data)
{
    ... return null if the object cannot be read as a datetime ...
}
Run Code Online (Sandbox Code Playgroud)

为您打算阅读的每种类型编写这样的方法.用户更愿意写:

DateTime? d = TryReadDateTime(data);
if (d != null) ...
Run Code Online (Sandbox Code Playgroud)

DateTime d;
bool b = TryRead<DateTime>(data, out d);
if (b) ...
Run Code Online (Sandbox Code Playgroud)