I have the following method:
我有以下方法:
public static bool EquivalentTo<T>(this T? current, T? compare)
where T : class
{
if (current is null && compare is null)
// both are null
return true;
if (current is null || compare is null)
// one is null, but not both
return false;
return current.Equals(compare);
}
IL Spy gives the following IL in Release build:
IL Spy在发布版本中提供了以下IL:
.method public hidebysig static
bool EquivalentTo<class T> (
!!T current,
!!T compare
) cil managed aggressiveinlining
{
.custom instance void [System.Runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = (
01 00 00 00
)
.param type T
.custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = (
01 00 01 00 00
)
// Method begins at RVA 0x4971
// Header size: 1
// Code size: 54 (0x36)
.maxstack 8
IL_0000: ldarg.0
IL_0001: box !!T
IL_0006: brtrue.s IL_0012
IL_0008: ldarg.1
IL_0009: box !!T
IL_000e: brtrue.s IL_0012
IL_0010: ldc.i4.1
IL_0011: ret
IL_0012: ldarg.0
IL_0013: box !!T
IL_0018: brfalse.s IL_0022
IL_001a: ldarg.1
IL_001b: box !!T
IL_0020: brtrue.s IL_0024
IL_0022: ldc.i4.0
IL_0023: ret
IL_0024: ldarg.0
IL_0025: box !!T
IL_002a: ldarg.1
IL_002b: box !!T
IL_0030: callvirt instance bool [System.Runtime]System.Object::Equals(object)
IL_0035: ret
} // end of method Extensions::EquivalentTo
I compiled with Visual Studio 2022 and .Net 8.0.100-preview.7.23376.3
in 64-bit.
我是用64位的Visual Studio 2022和.Net 8.0.100-preview.7.23376.3编译的。
I don't understand why there is boxing when the generic type is constrained to a class
and thus cannot be a value type. What am I missing?
我不明白当泛型类型被约束到一个类从而不能是值类型时,为什么会有装箱。我遗漏了什么?
更多回答
CIL isn't optimized at compile-time, optimization is a jitter duty and happens at runtime. Use Debug > Windows > Disassembly to see that the box generates no code.
CIL不是在编译时优化的,优化是一种抖动任务,在运行时发生。使用“调试”>“窗口”>“反汇编”可以看到该框不生成任何代码。
I guess Roslyn just doesn't perform this optimization, but it shouldn't affect performance since boxing a class is no-op and will be eliminated by JIT. Only downside is that each instruction adds 5 byte to result assembly, which may be significant if a lot of such checks are performed
我猜Roslyn只是不执行这种优化,但它不应该影响性能,因为装箱一个类是没有操作的,将被JIT消除。唯一的缺点是每条指令都会向结果汇编添加5个字节,如果执行了大量此类检查,这可能会很重要
优秀答案推荐
box !!T
br.true
or br.false
sequence is always a no-op for structs.
Box!!t br.true或br.False序列始终是结构的无操作。
Since the JITter compiles separate code for all struct (valuetype) generic code, it can see that a box would never result in a null, so it is elided. In the case of classes (reference types) it just does a normal null check.
因为抖动为所有结构(值类型)泛型代码编译单独的代码,所以它可以看到框永远不会导致空值,因此它被省略。对于类(引用类型),它只执行正常的空检查。
You can see this if you look at the JIT ASM machine code that is generated for both structs and classes.
如果您查看为结构和类生成的JIT ASM机器码,就可以看到这一点。
更多回答
我是一名优秀的程序员,十分优秀!