【问题标题】:Performance differences between overloading or optional parameters?重载或可选参数之间的性能差异?
【发布时间】:2013-10-25 06:47:30
【问题描述】:

我想知道我是否应该在 C# 中使用可选参数。直到现在我一直在重载方法。但是可选参数也很好,更简洁,代码更少。而且我在其他语言中使用它们,所以我也以某种方式习惯了它们。有什么反对使用它们的吗?性能对我来说是第一个关键点。会掉吗?


示例代码:
class Program
{
    // overloading
    private static void test1(string text1)
    {
        Console.WriteLine(text1 + " " + "world");
    }

    private static void test1(string text1, string text2)
    {
        Console.WriteLine(text1 + " " + text2);
    }

    // optional parameters
    private static void test2(string text1, string text2 = "world")
    {
        Console.WriteLine(text1 + " " + text2);
    }

    static void Main(string[] args)
    {
        test1("hello");
        test1("hello", "guest");

        test2("hello"); // transforms to test2("hello", "world"); ?
        test2("hello", "guest");

        Console.ReadKey();
    }
}


我测量了数百万次重载调用和可选参数调用所需的时间。
  • 带字符串的可选参数:18 % slower(2 个参数,发布)
  • 带整数的可选参数:更快(2 个参数,发布)

(也许编译器会优化或在未来优化那些可选参数调用?)

【问题讨论】:

标签: c# performance overloading optional-parameters


【解决方案1】:

我刚刚做了一个快速测试,编译器优化了代码。这个基本示例 Main 方法。

public static void OptionalParamMethod(bool input, string input2 = null)
{
}

public static void Main(string[] args)
{
    OptionalParamMethod(true);
    OptionalParamMethod(false, "hello");
}

编译为此,因此编译器填充可选参数。

public static void Main(string[] args)
{
    OptionalParamMethod(true, null);
    OptionalParamMethod(false, "hello");
}

至于性能,您可能会争辩说可选参数有一点优势,因为只有一个方法调用,而不是像您通常对重载方法那样的链式方法调用。下面的代码是编译输出以显示我在说什么。 difference 非常学术,但我怀疑您在实践中会注意到。

public static void Main(string[] args)
{
    OptionalParamMethod(true, null);
    OptionalParamMethod(false, "hello");
    OverloadParamMethod(true);
    OverloadParamMethod(false, "hello");
}

public static void OptionalParamMethod(bool input, [Optional, DefaultParameterValue(null)] string input2)
{
    Console.WriteLine("OptionalParamMethod");
}

public static void OverloadParamMethod(bool input)
{
    OverloadParamMethod(input, null);
}

public static void OverloadParamMethod(bool input, string input2)
{
    Console.WriteLine("OverloadParamMethod");
}

【讨论】:

  • 您能告诉我您如何查看优化后的代码吗?这对我来说似乎是性能下降。是吗?
  • Reflector 可让您查看已编译的代码。它编译为与任何普通方法调用相同,没有性能下降。 PS 这是一个调试版本,如果它是一个发布版本,那么编译器实际上会完全删除方法调用,因为该方法是一个 NOP。
  • 但是当你调用一个带有 1 个参数的重载方法时,会发送 1 个对象。当您调用带有 2 个参数的可选参数方法并且优化代码发送所有参数(使用默认值)时,会使用更多的堆栈空间,并且需要更多的时间来复制值和引用。
  • 刚刚添加了更多答案。通常,您使用可选参数,您将使用重载方法进行方法链接。如果这不是您想要达到的目标,那么您需要根据每个案例的优点来评估每个案例,但一般而言,可选参数可能会赢得性能。
  • -1 由于重载或可选参数(在运行时),没有性能损失。 stackoverflow.com/questions/3581747/…
【解决方案2】:

重载和可选参数本身都不会导致性能发生任何变化。正如 David Ewen 所指出的,C# 编译器生成的 IL 不知道可选参数(这是一些版本控制错误的来源,这些错误来自可以是文字的类型的可选参数)。

至于重载。 C# 是(大部分)静态类型语言。编译后的代码直接引用相应方法的地址。在编译时重载时,性能会受到很小的影响。实际上,在 C++ 中,重载是由一个称为“名称修改”的过程完成的,其中每个重载在编译时都被赋予一个唯一的名称。

但在某些情况下,CAN 过载会影响性能。但这些都非常明显,例如在反射和动态类型代码中。

听起来您对虚拟/抽象函数的性能影响感到困惑。为了让 .net 运行时解析正确的函数,有一个额外的步骤来查找该方法的特定类型的实现。

【讨论】:

    猜你喜欢
    • 2015-11-29
    • 1970-01-01
    • 1970-01-01
    • 2020-02-11
    • 1970-01-01
    • 2011-08-13
    • 2015-10-12
    • 2014-03-03
    • 2019-09-16
    相关资源
    最近更新 更多