如何将System.Type转换为其可为空的版本?

时间:2020-03-06 14:29:02  来源:igfitidea点击:

再说一遍:"是否有一种比我的助手方法更简单的内置处理方式?"

因此,从可为空的类型获取基础类型很容易,但是如何获取.NET类型的可为空的版本呢?

所以我有

typeof(int)
typeof(DateTime)
System.Type t = something;

而且我要

int? 
DateTime?

或者

Nullable<int> (which is the same)
if (t is primitive) then Nullable<T> else just T

有内置的方法吗?

解决方案

这是我使用的代码:

Type GetNullableType(Type type) {
    // Use Nullable.GetUnderlyingType() to remove the Nullable<T> wrapper if type is already nullable.
    type = Nullable.GetUnderlyingType(type);
    if (type.IsValueType)
        return typeof(Nullable<>).MakeGenericType(type);
    else
        return type;
}

我没有任何内建的东西,例如int等只是Nullable <T>的语法糖。并且没有得到特别的待遇。鉴于我们尝试从给定类型的类型信息中获取此信息,这种情况特别不可能发生。通常,这总是需要一定的"滚动自己的"代码。我们将必须使用Reflection创建一个带有输入类型的type参数的新的" Nullable"类型。

编辑:正如评论所建议的那样,实际上对Nullable &lt;>进行了特殊处理,并在运行时按照本文中的说明进行了引导。

Lyman的回答很好,对我有所帮助,但是,还有一个错误需要修复。

仅当类型尚未为Nullable类型时,才应调用Nullable.GetUnderlyingType(type)。否则,当类型从System.RuntimeType派生时(例如当我传入typeof(System.Int32)时),它似乎错误地返回了null。下面的版本通过检查类型是否为Nullable来避免调用Nullable.GetUnderlyingType(type)。

在下面,我们将找到此方法的ExtensionMethod版本,该版本将立即返回类型,除非它是不是NullableValueType

Type NullableVersion(this Type sourceType)
{
    if(sourceType == null)
    {
        // Throw System.ArgumentNullException or return null, your preference
    }
    else if(sourceType == typeof(void))
    { // Special Handling - known cases where Exceptions would be thrown
        return null; // There is no Nullable version of void
    }

    return !sourceType.IsValueType
            || (sourceType.IsGenericType
               && sourceType.GetGenericTypeDefinition() == typeof(Nullable<>) )
        ? sourceType
        : typeof(Nullable<>).MakeGenericType(sourceType);
}

(对不起,但我不能简单地在莱曼的答案中发表评论,因为我是新来的,并且没有足够的代表。)