如何通过一个密封类实现编译器优化虚拟方法

如何通过一个密封类实现编译器优化虚拟方法

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

问题描述

我不知道下面的代码是如何优化。特别是关于虚拟和直接调用。我已经谈到如何,我认为一切都在优化,但这些都只是猜测。

 公共抽象类超
{
酒店的公共抽象无效美孚();

公共无效FooUser()
{
美孚();
}
}

公共类Child1:超
{
公众覆盖无效美孚()
{
// DoSomething的
}
}

公共类SealedChild:超
{
公众覆盖无效美孚()
{
// DoSomething的
}
}

类节目
{
无效的主要()
{
Child1 child1 =新Child1();
child1.Foo(); //虚拟呼叫?
child1.FooUser(); //直接调用,然后虚拟呼叫。

SealedChild sealedChild =新SealedChild();
sealedChild.Foo(); //直接调用?
sealedChild.FooUser();
/ *两个选择:要么直接调用&安培;那么虚拟呼叫
*或者:使用具有一个函数指针foo的参数,然后直接调用直接调用foo中。
* /

超超级= child1;
super.Foo(); //虚拟呼叫。
super.FooUser(); //虚拟呼叫然后直接调用。
}
}


解决方案

在在这里你有一个密封类虚方法和对象引用的类型的情况下是密封类是可以避免的虚拟呼叫。看看下面的例子。有是的GetName需要被称为虚拟因为我们知道不可能有子类家长,因此没有进一步的虚拟调度没有实际的原因。

 密封类家长:儿童{
公共重写字符串的GetName(){返回富; }
}

公共无效测试(){
变种P =新的父();
变种名称= p.GetName();
}

一个编译器可以选择注意到这一点,并输出一个呼叫IL指令,而不是callvirt。然而无论是C#和VB.Net编译器选择不执行该优化。双方将发出callvirt。



的JIT也自由地做出这样的优化。它也选择不。







这并不意味着但是你不应该封你的班。类应密封,除非你打算居然有人从他们那里继承。否则,你打开你自己给你未能准确成本情形。



此外,并没有什么东西在稍后的日期执行这一停止编译器和JIT。


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.
    }
}
解决方案

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();
}

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.

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.

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

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

08-20 19:37