可空类型不是可以为空的类型?

Bla*_*son 44 .net c# nullable gettype

我正在使用可空类型进行一些测试,并且它没有像我预期的那样工作:

int? testInt = 0;
Type nullableType = typeof(int?);
Assert.AreEqual(nullableType, testInt.GetType()); // not the same type
Run Code Online (Sandbox Code Playgroud)

这也不起作用:

DateTime? test = new DateTime(434523452345);
Assert.IsTrue(test.GetType() == typeof(Nullable)); //FAIL 

DateTime? test = new DateTime(434523452345);
Assert.IsTrue(test.GetType() == typeof(Nullable<>)); //STILL FAIL
Run Code Online (Sandbox Code Playgroud)

我的问题是为什么testInt.GetType()返回int,而typeof(int?)返回真正的可空类型?

Rom*_*ier 56

根据MSDN:

在Nullable类型上调用GetType会导致在将类型隐式转换为Object时执行装箱操作.因此,GetType始终返回表示基础类型的Type对象,而不是Nullable类型.

当您装入可以为空的对象时,只有底层类型被装箱.

再次,来自MSDN:

装箱非空可空值类型框表示值类型本身,而不是包装值类型的System.Nullable.


Luk*_*keH 22

继Romain的正确答案之后,如果你想比较"真实"类型(即,没有隐式地将任何可空类型转换为其基础类型),那么你可以创建一个扩展方法,如下所示:

public static class MyExtensionMethods
{
    public static Type GetRealType<T>(this T source)
    {
        return typeof(T);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后尝试以下测试:

int? a = 0;
Console.WriteLine(a.GetRealType() == typeof(int?));         // True
Console.WriteLine(a.GetRealType() == typeof(int));          // False

int b = 0;
Console.WriteLine(b.GetRealType() == typeof(int));          // True
Console.WriteLine(b.GetRealType() == typeof(int?));         // False

DateTime? c = DateTime.Now;
Console.WriteLine(c.GetRealType() == typeof(DateTime?));    // True
Console.WriteLine(c.GetRealType() == typeof(DateTime));     // False

DateTime d = DateTime.Now;
Console.WriteLine(d.GetRealType() == typeof(DateTime));     // True
Console.WriteLine(d.GetRealType() == typeof(DateTime?));    // False
Run Code Online (Sandbox Code Playgroud)

编辑...

为了完整-通过以下SLaks的评论提示-这里的,只有当使用编译时类型的替代版本source或者是nullNullable<>; 否则它使用GetType并返回运行时类型:

public static class MyExtensionMethods
{
    public static Type GetRealType<T>(this T source)
    {
        Type t = typeof(T);

        if ((source == null) || (Nullable.GetUnderlyingType(t) != null))
            return t;

        return source.GetType();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这将获得_compile-time_类型. (2认同)