2

我想知道我是否应该在 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 % (2 个参数,释放)
  • 带整数的可选参数:<1 %更快(2 个参数,发布)

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

4

2 回答 2

3

我刚刚做了一个快速测试,编译器优化了代码。这个基本示例 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");
}

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

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");
}
于 2013-10-25T06:52:51.700 回答
3

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

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

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

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

于 2013-10-25T07:15:11.643 回答