【发布时间】:2010-06-28 12:48:24
【问题描述】:
虽然我知道出于安全原因可以使用sealed,但有些人在叶节点上使用sealed关键字作为一种优化技术。
这对优化有何帮助?为什么编译器不够聪明,无法自己解决这个问题?
【问题讨论】:
标签: c# optimization
虽然我知道出于安全原因可以使用sealed,但有些人在叶节点上使用sealed关键字作为一种优化技术。
这对优化有何帮助?为什么编译器不够聪明,无法自己解决这个问题?
【问题讨论】:
标签: c# optimization
假设您有一个在叶类中被覆盖的虚方法。这肯定不会被进一步覆盖,因此 JIT 编译器可能会内联调用已知属于该叶类的目标的该方法。请注意,我不知道 JIT 是否实际上执行了这种优化。
请注意,在 Java 中,HotSpot JVM 甚至可以对非最终类执行此优化,因为它是一个多通道 JIT:它可以乐观地假设没有任何东西会覆盖虚拟方法,然后如果出现确实覆盖它的类被加载。当然,在 Java 中默认方法是虚拟的,这比在 C# 中要大得多。 (即使默认值不应该很重要,但它们显然很重要。)
我个人不使用sealed,特别是出于优化或安全原因:我使用它是因为(正确地)设计继承是困难。我同意“为继承而设计或禁止它”的概念,并且通常发现无法从类派生的偶尔痛苦可以通过不必担心继承来弥补。 YMMV。
【讨论】:
在密封类中,对虚拟方法的调用可以绕过通常的虚拟方法查找,而直接转到派生最多的虚拟方法实现。原则上,编译器/JIT 也可以内联这些调用。
编译器无法确定非密封类的情况,因为任何代码都可能在编译后出现并从您的类继承:编译器必须假设最坏的情况。
【讨论】:
new NonSealedClass().Method();
不,它在优化方面并没有真正的帮助。无论如何,我无法从分析中看到。
【讨论】:
这是一个错误的优化;我宁愿用它来确保如果我不期望 继承,我不会得到 继承。编译器仍将所有实例调用(对类)作为虚拟调用发出,但可能 JIT 可以对其进行不同的优化,如果没有被覆盖,则只需进行空值检查和静态调用。可能。
还有一些更深奥的情况,例如,特定接口的存在会导致它在运行时受到不同的处理 - 但利用 那些 场景(取决于sealed)需要运行时通过ILGenerator 等生成代码
【讨论】: