网上有很多文章列出了C# JIT在执行一段代码之前所做的优化。例如this post在 MSDN 上讨论:
Constant folding, Constant and copy propagation, Common subexpression elimination, Code motion of loop invariants, Dead store and dead code elimination, Register allocation, Method inlining, Loop unrolling (small loops with small bodies).
我的问题是:JIT 编译器是否也处理无用的空值检查?我找不到任何来源来处理这个问题。
在我读到的同一篇文章中:
since the C# language specification ensures that any call on a null object reference throws a NullReferenceException, every call site must ensure the instance is not null. This is done by dereferencing the instance reference; if it is null it will generate a fault that is turned into this exception.
所以,假设我写了一段这样的代码:
if (person != null)
{
Console.WriteLine(person.Name);
}
person.Name
再次调用显然无用的第二个 null 检查,编译器可以将其删除。还是不行?
我读到在 Java 中这已经完成了(许多 here 、 here 和 here 之间的一些来源)。
如果 C# 也这样做,您是否知道一些讨论该问题的来源或文档?
如果 C# 不这样做,您知道为什么吗?在 Java JIT 不会遇到的 .NET 环境中实现这样的功能是否存在内在困难?
最佳答案
Null
检查编译器完成的优化(Roslyn,而非 Jitter)in several cases ,当它完全保存时。
例如,当您使用 ?
(Elvis 运算符)时。
IL_0006: stloc.0 // Pop a value from stack into local variable 0
IL_0007: ldloc.0 // Load local variable 0 onto stack
IL_0008: brtrue.s IL_000c // Branch to target if value is non-zero (true), short form
IL_000a: br.s IL_0013 // Branch to target, short form
IL_000c: ldloc.0 // Load local variable 0 onto stack
IL_000d: call instance void Foo::Bar() // Call method indicated on the stack with arguments
另一个例子是这样的代码:
new Bar().Foo();
编译器为这个 call
指令而不是 callvirt
生成(这意味着,没有对 this
进行空检查)
在其他情况下,您无法确定 this
不会为 null。
不管怎样,null 检查真的非常快。
关于c# - C# JIT 编译器是否优化空值检查?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41004069/