3

.Net 中的重载方法是否会产生成本?

因此,如果我有 3 种方法,例如:

Calculate (int)
Calculate (float)
Calculate (double)

并且这些方法在运行时根据传递给Calculate方法的内容“动态”调用,这种重载解决方案的成本是多少?

或者,我可以有一个计算并在方法主体中产生差异,但我认为这需要方法在每次调用时评估类型。

有没有更好的方法/设计来解决这个问题而可能没有开销?或者更好的是,处理此类案件的最佳做法是什么?我想有相同的类/方法名,但不同的行为。

编辑:谢谢大家。如果它有任何不同,那就只做一件事。我想知道你有一个用于这些方法的 DLL 和一个用 C# 编写的程序,它允许用户将这些方法添加为 UI 项(无需指定类型)。所以用户添加UI项Calculate(5),然后Calculate(12.5)等,C#app执行这个,还会没有开销吗?

4

7 回答 7

15

就运行时而言,这些是不同的方法。和写法一样:

CalculateInt(int)
CalculateFloat(float)

关于性能问题,除了非常特殊的情况,您可以放心地忽略方法调用开销。

于 2009-02-26T22:32:29.927 回答
9

这个问题是关于方法重载,而不是多态性。据我所知,方法重载不会受到惩罚,因为编译器会根据传递给它的参数类型确定在编译时调用哪个方法。

多态性仅在您使用派生类型代替基类时发挥作用。

于 2009-02-26T22:33:33.670 回答
7

首先,除非您的分析器告诉您存在性能问题,否则您不应该为了假设的性能提升而牺牲良好的设计。

要回答您的问题,方法调用的解决方案不是动态的。它是在编译时确定的,因此在这方面没有成本。唯一的成本是潜在的隐式类型转换以适应参数类型。

于 2009-02-26T22:32:35.293 回答
4

方法重载(即方法表槽)不是在运行时动态解析的,而是在编译时静态解析的,因此重载方法的成本为零。

我假设您正在考虑virtual实际实现可能被派生类型覆盖的方法,并且根据具体类型选择实际方法。但这与重载无关,因为虚拟方法占用相同的方法表槽。

于 2009-02-26T22:33:54.777 回答
2

运行时没有“成本”,因为编译器决定在编译时调用哪个方法。生成的 IL 专门调用采用适当参数的方法。

以这个为例”

public class Calculator
{
    public void Calculate(int value)
    {
        //Do Something
    }
    public void Calculate(decimal value)
    {
        //Do Something
    }
    public void Calculate(double value)
    {
        //Do Something
    }
}

static void Main(string[] args)
{
    int i = 0;
    Calculator calculator = new Calculator();
    calculator.Calculate(i);
}

在 IL 中进行以下调用以计算变量“i”:

L_000b: callvirt instance void ConsoleApplication1.Calculator::Calculate(int32)

请注意,它指定方法是 int32 类型,它与从 Main 方法传入的变量类型相同。

因此,如果完全有成本,那只是在编译时。不用担心。

正如JaredPar在下面指出的:

你的问题存在误解。C# 中的重载方法不会在运行时动态调用。所有方法调用都在编译时静态绑定。因此,在运行时没有“搜索”方法,它在编译时预先确定了将调用哪个重载。

于 2009-02-26T22:44:14.457 回答
1

根据类型在 IL 中产生 3 种不同的方法。唯一的成本是您从一种类型转换为另一种类型,但除非您有大量工作要做,否则该成本不会很大。因此,您可以坚持使用 Calculate(double) 并从那里进行投射。

于 2009-02-26T22:30:03.617 回答
1

你的问题存在误解。C# 中的重载方法不会在运行时动态调用。所有方法调用都在编译时静态绑定。因此,在运行时没有“搜索”方法,它在编译时预先确定了将调用哪个重载。

注意:这在 C# 4.0 和动态版本中有所改变。对于动态对象,可能会在运行时根据对象的类型选择重载。但是,C# 3.0 及更低版本并非如此。

于 2009-02-27T04:46:22.463 回答