C# 可空类型不是可空类型吗?
我用可空类型进行了一些测试,但它并没有像我预期的那样工作:C# 可空类型不是可空类型吗?,c#,.net,nullable,gettype,C#,.net,Nullable,Gettype,我用可空类型进行了一些测试,但它并没有像我预期的那样工作: int? testInt = 0; Type nullableType = typeof(int?); Assert.AreEqual(nullableType, testInt.GetType()); // not the same type 这也不起作用: DateTime? test = new DateTime(434523452345); Assert.IsTrue(test.GetType() == typeof(Null
int? testInt = 0;
Type nullableType = typeof(int?);
Assert.AreEqual(nullableType, testInt.GetType()); // not the same type
这也不起作用:
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
DateTime?测试=新日期时间(43452345235);
Assert.IsTrue(test.GetType()==typeof(null))//失败
约会时间?测试=新日期时间(43452345235);
Assert.IsTrue(test.GetType()==typeof(null))//仍然失败
我的问题是为什么testInt.GetType()返回int,而typeof(int?)返回真正的可为null的类型?根据:
对可为空的类型调用GetType
使装箱操作失败
当类型为隐式时执行
转换为对象。因此GetType
始终返回一个
表示基础类型,而不是
可为空的类型
当您装箱一个可为空的对象时,只装箱基础类型
同样,来自:
装箱一个非空的可空值类型
框中的值类型本身,而不是
包装该值的System.Nullable
类型
根据Romain的正确答案,如果要比较“真实”类型(即,不隐式地将任何可空类型转换为其基础类型),则可以创建如下扩展方法:
public static class MyExtensionMethods
{
public static Type GetRealType<T>(this T source)
{
return typeof(T);
}
}
编辑…
为了完整性——并根据SLaks下面的评论——这里有一个替代版本,它只在source
为null
或可为null
时使用编译时类型;否则,它使用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();
}
}
公共静态类MyExtensionMethods
{
公共静态类型GetRealType(此T源)
{
类型t=类型(t);
if((source==null)| |(null.getUnderlineType(t)!=null))
返回t;
返回source.GetType();
}
}
尽管C#假装值类型存储位置保存从System.ValueType
派生的类型的实例,而后者又从System.Object
派生,但事实并非如此。从System.ValueType
派生的每种类型实际上代表两种截然不同的事物:
Nullable
只支持第一次使用。如果试图将类型为Nullable
的存储位置传递给希望引用堆对象的代码,则如果HasValue
为true,系统将该项转换为T
,或者如果HasValue
为false,则只传递null引用。虽然有一些方法可以创建类型为Nullable
的堆对象,但是将值类型存储位置转换为堆对象的常规方法永远不会生成堆对象
还要注意,对值存储位置调用
GetType()
实际上不会计算存储位置的类型,而是将该存储位置的内容转换为堆对象,然后返回结果对象的类型。由于类型为Nullable
的存储位置被转换为T
的对象实例或null,因此对象实例中的任何内容都不会说明其来源的存储位置是否为Nullable一种使用“is”操作符检查的简单方法:
(i is Nullable<int>) || (i is Nullable<long>) || (i is Nullable<float>) || (i is Nullable<short>)
(i可为空)| |(i可为空)| |(i可为空)| |(i可为空)
我发现ti正在阅读这两个MSDN页面:
干杯 请注意,这将获得编译时类型。@SLaks:是否有过nullable的运行时类型与编译时类型不同的情况?(我很感激您可以将任何类型传递给这个方法,在这种情况下,您确实可以获得运行时类型,但它的目的是获得可为null的“真实”类型,正如问题所述。)您是对的<代码>((int?)2)。GetRealType()
实际上不算数<代码>((对象)可空)。GetRealType()不明确。@SLaks:Oops,我的意思是“…在这种情况下,您确实会得到编译时类型”。是的,当您调用((object)nullable).GetRealType()
时,您将不再传递一个nullable。您正在传递nullable的基础类型的装箱值,或者只传递纯null。您可以提到,为了使用第二个版本,不能装箱nullable变量。另外,将您的第一个版本重命名为GetCompileType可以清楚地了解此方法的真正功能。它的伸缩性不是很好,是吗?可为空的、可为空的等
(i is Nullable<int>) || (i is Nullable<long>) || (i is Nullable<float>) || (i is Nullable<short>)