编译器如何优化密封类实现的虚方法 [英] How does compiler optimize virtual methods implemented by a sealed class

查看:32
本文介绍了编译器如何优化密封类实现的虚方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道以下代码是如何优化的.特别是关于虚拟和直接呼叫.我已经评论过我认为一切都经过优化的方式,但这些只是猜测.

I'm wondering how the following code is optimized. Specifically concerning virtual and direct calls. I have commented on how I think everything is optimized but those are just guesses.

public abstract class Super
{
    public abstract void Foo();

    public void FooUser()
    {
        Foo();
    }
}

public class Child1 : Super
{
    public override void Foo()
    {
        //doSomething
    }
}

public class SealedChild : Super
{
    public override void Foo()
    {
        //doSomething
    }
}

class Program
{
    void main()
    {
        Child1 child1 = new Child1();
        child1.Foo(); //Virtual call?
        child1.FooUser(); //Direct call and then a virtual call. 

        SealedChild sealedChild = new SealedChild();
        sealedChild.Foo(); //Direct call?
        sealedChild.FooUser(); 
        /* Two options: either a direct call & then a virtual call
         * Or: direct call with a parameter that has a function pointer to Foo, and then a direct call to foo.
         */

        Super super = child1;
        super.Foo(); //Virtual call.
        super.FooUser(); //Virtual call then direct call.
    }
}

推荐答案

如果密封类上有虚方法,并且对象引用的类型是密封类,则可以避免虚调用.以下面的例子为例.没有实际原因需要虚拟调用 GetName,因为我们知道不能有 Parent 的子类,因此没有进一步的虚拟调度.

In the case where you have a virtual method on a sealed class, and the type of the object reference is the sealed class the virtual call could be avoided. Take the following example. There is no actual reason that GetName needs to be called virtually because we know there can be no sub class of Parent and hence no further virtual dispatch.

sealed class Parent : Child  {
  public override string GetName() { return "foo"; }
}

public void Test() {
  var p = new Parent();
  var name = p.GetName();
}

编译器可以选择注意到这一点并输出 call IL 指令而不是 callvirt.但是,C# 和 VB.Net 编译器都选择不执行此优化.两者都会发出 callvirt.

A compiler could choose to notice this and output a call IL instruction instead of a callvirt. However both the C# and VB.Net Compiler choose not to perform this optimization. Both will emit callvirt.

JIT 也可以自由进行这样的优化.它也选择不这样做.

The JIT is also free to make such an optimization. It also chooses not to.

但这并不意味着你不应该密封你的类.类应该是密封的,除非你真的打算让某人继承它们.否则,您将面临无法准确计算成本的情况.

That does not mean however that you should not seal your classes. Classes should be sealed unless you actually intend for someone to inherit from them. Otherwise you're opening yourself up to scenarios you have failed to accurately cost.

此外,没有什么能阻止编译器和 JIT 在以后实现这一点.

Additionally, there's nothing stopping the compilers and JIT from implementing this at a later date.

这篇关于编译器如何优化密封类实现的虚方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆