C# Net中的方法重载开销

C# Net中的方法重载开销,c#,.net,methods,overloading,C#,.net,Methods,Overloading,在.Net中重载方法是否有成本 如果我有3种方法,比如: Calculate (int) Calculate (float) Calculate (double) 这些方法在运行时根据传递给Calculate方法的内容“动态”调用,这种重载解析的代价是什么 或者,我可以进行一次计算,并在方法体中进行更改,但我认为这需要方法在每次调用时对类型进行求值 有没有更好的方法/设计来解决这个问题,而不需要额外的开销?或者更好的是,处理此类案件的最佳实践是什么?我希望具有相同的类/方法名称,但行为不同 编

在.Net中重载方法是否有成本

如果我有3种方法,比如:

Calculate (int)
Calculate (float)
Calculate (double)
这些方法在运行时根据传递给Calculate方法的内容“动态”调用,这种重载解析的代价是什么

或者,我可以进行一次计算,并在方法体中进行更改,但我认为这需要方法在每次调用时对类型进行求值

有没有更好的方法/设计来解决这个问题,而不需要额外的开销?或者更好的是,处理此类案件的最佳实践是什么?我希望具有相同的类/方法名称,但行为不同


编辑:谢谢大家。只要一件事,如果有什么不同。我想知道您是否有一个用于这些方法的DLL和一个用C#编写的程序,该程序允许用户将这些方法添加为UI项(而不指定类型)。因此,用户添加UI项Calculate(5),然后Calculate(12.5)等,C#app执行此操作,是否仍然没有开销?

3种不同的方法根据类型在IL中生成。唯一的成本是,如果你从一种类型铸造到另一种类型,但除非你有大量的工作要做,否则成本不会很大。因此,您可以坚持计算(double)并从那里进行转换。

就运行时而言,这些方法是不同的。与写作相同:

CalculateInt(int)
CalculateFloat(float)

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

首先,除非探查器告诉您存在性能问题,否则您不应该为了假定的性能增益而牺牲良好的设计


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

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

多态性只在使用派生类型替换基类时才起作用。

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

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

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

以此为例"

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

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

所以,如果有成本的话,那只是在编译时。不用担心

如下所述:


你的问题中有一个误解。C#中的重载方法是 在运行时未动态调用。全部 方法调用静态绑定在 编译时。因此没有 在运行时“搜索”方法, 它是在编译时预先确定的 将调用哪个重载


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


注意:对于C#4.0和dynamic,这会有一些变化。对于dynamic对象,可能会在运行时根据对象的类型选择重载。但对于C#3.0及以下版本,情况并非如此。

这个问题是关于方法重载的,这与多态性完全不同。@Cris:.NET per instruction cost是实际上没有什么,大多数情况下框架加载时间是一个问题(现在大约500毫秒?)是的……你必须研究重载与重写。优化这一点的一种方法是使用泛型。@约翰:你是说我的3计算方法案例?@Aleris:什么样的特殊案例?@Chris:例如,使用“内联”方法进行向量数学(代码复制的方式和C中的宏一样,如果优化的级别需要内联方法,现在是移到C++的时候了):谢谢你指出明显的(不是讽刺的,我赞成的)。
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);
}
L_000b: callvirt instance void ConsoleApplication1.Calculator::Calculate(int32)