【发布时间】:2017-03-07 00:14:46
【问题描述】:
class C<T> where T : struct {
bool M1(object o) => o is T;
bool M2(object o) => o is T?;
}
在传递null 引用或装箱T 值时,上述两种方法的行为似乎相同。不过生成的 MSIL 代码有点不同:
.method private hidebysig instance bool M1(object o) cil managed {
.maxstack 8
IL_0000: ldarg.1
IL_0001: isinst !T
IL_0006: ldnull
IL_0007: cgt.un
IL_0009: ret
}
对
.method private hidebysig instance bool M2(object o) cil managed {
.maxstack 8
IL_0000: ldarg.1
IL_0001: isinst valuetype [mscorlib]System.Nullable`1<!T>
IL_0006: ldnull
IL_0007: cgt.un
IL_0009: ret
}
如您所见,o is T? 表达式实际上对 Nullable<T> 类型执行类型检查,尽管 CLR 专门处理可空类型以便 C# 将装箱的 T? 值表示为 null 引用(如果T? 没有值)或装箱的 T 值。似乎不可能在纯 C# 或什至在 C++/CLI 中获得Nullable<T> 类型的框(因为运行时处理box 操作码以支持此“T? => T 框/null”装箱)。
我是否遗漏了什么或者o is T?实际上等同于C#中的o is T?
【问题讨论】:
-
对于这样一个令人困惑的问题,有很多赞成票。你到底在这里问什么?您的标题的答案很明显:IL 表明实际上存在差异。但是您的问题似乎是在询问您是否可以装箱
Nullable<T>对象。请解决您的问题,以便您清楚地了解您想要找出的内容。 -
我在问“
o is T?是否实际上等同于 C# 中的o is T”,它是尽可能清晰 :) -
“实际上等效”以什么方式?在您看来,哪种形式的对等不是“实用的”?我认为
M2()永远不会返回true,所以这对我来说似乎不实用,也不等效。 -
您对 C# 中的
is被编译为 CIL 中的isinst这两种类型感到惊讶吗,因为Nullable<T>是由 CLR 专门处理的?这正是它被编译为相同内容的原因,因此 C# 编译器不必处理可为空的恶作剧。
标签: c# types nullable cil boxing