【发布时间】:2017-04-21 14:32:40
【问题描述】:
网上有很多文章列出了 C# JIT 在执行一段代码之前所做的优化。比如MSDN上的this post谈:
常量折叠、常量和复制传播、公共子表达式 消除,循环不变量的代码运动,死存储和死代码 消除、寄存器分配、方法内联、循环展开 (带有小主体的小环)。
我的问题是:JIT 编译器是否也处理无用的空检查?我找不到任何处理这个问题的来源。
在我读到的同一篇文章中:
因为 C# 语言规范确保对 null 的任何调用 对象引用抛出 NullReferenceException,每个调用站点都必须 确保实例不为空。这是通过取消引用 实例参考;如果它为空,它将产生一个错误,即 变成了这个异常。
那么,假设我这样写一段代码:
if (person != null)
{
Console.WriteLine(person.Name);
}
person.Name 再次调用了第二个空检查,这显然是无用的,编译器可以将其删除。还是不行?
我读到在 Java 中这已经完成(许多 here、here 和 here 之间的一些来源)。
如果 C# 也这样做,您是否知道一些相关的资料或文档?
如果 C# 不这样做,你知道为什么吗?在 Java JIT 没有遇到的 .NET 环境中实现这样的功能是否存在内在困难?
【问题讨论】:
-
仅作为正常优化的副作用,如死代码消除。这应该很少见。一般来说,抖动优化器没有执行空指针检查的代码的特殊知识,并将指针视为易失性。在任何带有垃圾收集器的 VM 中都非常重要,该垃圾收集器在压缩堆时会任意修改指针。值得注意的是,C# 编译器本身可以消除检查,当您使用 elvis 运算符 (
?.) 时会这样做。
标签: c# .net optimization jit null-check