2017-02-27 64 views
1

好的,也许这不是最聪明的问题,但我不能让我的头靠近它。我想知道方法重载的性能。这是说明我的问题一个简单的例子:方法超载的性能

class testadd 
{ 
    public double _a { get; set; } 
    public double _b { get; set; } 
    public double add(double a, double b) 
    { 
     return a + b; 
    } 
    public double add() 
    { 
     return add(_a, _b); 
    } 
} 

如果我现在有这个类的一个实例,调用add(),像这样:

 var tadd = new testadd(); 
     tadd._a = 1; 
     tadd._b = 3; 
     Console.WriteLine(tadd.add()); 

不认为需要两个方法调用,首先添加(),然后添加(双a,双b)?如果你有一个更广泛的方法,这是一个很好的选择,因为我不必重新键入函数体,但如果它的性能降低,这可能仍然不是要走的路。或者编译器是否知道这一点,我不需要担心这一点?

+0

您是否尝试过在带有秒表的巨大循环中运行两者(无印记)?反编译结果代码? – AFract

+3

不要让参数成员成为参数。这个问题也与重载无关,你的'add()'也可以被称为'foo()'。问题在于调用链中的额外方法是否有明显的性能影响。即使它有,你会怎么做呢? – CodeCaster

+0

对不起,你能否详细说明你的第一部分?我不是专家。我可以做些什么,以及我可以简单地将函数体复制到两种方法中以保存一个调用 – nik

回答

2

首先要注意的是,C#编译的CIL在调用哪种方法时非常明确,因此在计算应调用哪个版本的方法时没有运行时开销。

重载的成本和收益完全是语义的;他们通过两者之一(如果使用得很好)将一个或多个人的公共表面或多或少地理解为一个人可以清楚地理解为相同操作的变体,其中它们之间的差异可以合理地猜测并记录在后面(尤其是一个是另一个具有“默认”值的变体),否则(如果使用得不好)给不同的操作以相同的名称。

接下来要注意的是,小的简单*方法可以预期内联,因此调用tadd.add()的代价(无论如何,在发布版本中)几乎与直接调用tadd.add(tadd._a, tadd._b)的代价相同。即使_a_bprivate,并且直接调用该表单将不被允许:private是C#代码可以执行的操作的限制,而不是编译器或抖动可以执行的操作。它也有好处,如果tadd是一个领域,它只会加载一次,而不是三次。

超载实际上可以作为一个微型的优化,如果我们有Foo(int a, int b, int c)c一个原因是0为广大调用,那么添加Foo(int a, int b) => Foo(a, b, 0)可以减少调用方法的大小,所以有时使他们更可能的依次内联。这绝对是一种微型优化,尽管大部分时间都不值得为其自身而做。 99.9%的重载时间应该是因为它使代码更清晰。应该测量0.1%以确保它实际上在热路中有帮助。 (我仍然认为重载的成本和收益完全是上面的语义,因为在确实有帮助的情况下,调用该方法会有所帮助,重载本身没有性能影响)。

*“简单”虽然不一定是一件简单的事情,“小”是相对的,但任何一次调用都没有包含在隐式或显式try块中,不是虚拟的,并且不能处理大值类型很可能被内联。