con*_*low 11 c# boxing types cil nullable
class C<T> where T : struct {
bool M1(object o) => o is T;
bool M2(object o) => o is T?;
}
Run Code Online (Sandbox Code Playgroud)
传递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
}
Run Code Online (Sandbox Code Playgroud)
VS
.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
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,o is T?表达式实际上对Nullable<T>类型执行类型检查,尽管CLR专门处理可空类型,因此C#表示盒装T?值作为null引用(如果T?没有值)或盒装T值.似乎不可能Nullable<T>在纯C#或甚至在C++/CLI 中获得类型的盒子(因为运行时处理box操作码以支持这种" T?=> T盒子/ null"拳击).
我在C#中遗漏了什么或o is T?几乎等同o is T于?
根据规范(强调我的),in E is T,非可空值类型T和相应的可空类型以相同的方式处理:
7.10.10
is操作员的
is操作者用于动态检查是否一个对象的运行时类型是与给定类型兼容.操作的结果E is T,其中E是表达式并且T是类型,是一个布尔值,指示是否E可以T通过引用转换,装箱转换或取消装箱转换成功转换为类型.在使用类型参数替换所有类型参数之后,将按如下方式评估操作:
如果
E是匿名函数,则发生编译时错误如果
E是方法组或空文字,如果类型E是引用类型或可空类型且E的值为null,则结果为false.否则,让我们
D表示动态类型E如下:
- 如果类型
E是引用类型,D则是实例引用的运行时类型E.如果类型
E是可空类型,D则是该可空类型的基础类型.如果类型
E是非可空值类型,D则是类型E.操作的结果取决于
D并T如下:
- 如果
T是引用类型,其结果是,如果真D和T是相同的类型,如果D是引用类型和从隐式引用转换D到T存在,或者如果D是一个值类型和从一个装箱转换D到T存在.- 如果
T是可空类型,则结果为true,如果D是基础类型T.- 如果
T是非可空值类型,则结果为true,如果D且T是相同类型.- 否则,结果为false.