4

在 .NET 框架中有许多示例,其中一个方法有多个重载,其中一些使用特定数量的参数,然后params是使用关键字的最终“catch all”。常见的例子是在String课堂上,例如:

我想知道为什么有这么多这些方法重载是否有特殊原因?起初我认为这可能与性能有关;这个 SO 问题的问题和答案 -在 C# 中使用参数的成本- 会建议这样做。

但是,我开始使用Reference Source网站深入研究 .NET 源代码。我在String 类源代码中注意到了这一点:

String.Concat()实际上根据使用了多少固定参数运行不同的代码——在我看来这肯定是一种优化。String.Format()但是似乎只是提供了 mainparam方法的包装器 - 请参阅下面的释义代码:

public static String Format(String format, Object arg0)
{
    return Format(format, new Object[] { arg0 });
}

public static String Format(String format, Object arg0, Object arg1)
{
    return Format(format, new Object[] { arg0, arg1 });
}

public static String Format(String format, Object arg0, Object arg1, Object arg2)
{
    return Format(format, new Object[] { arg0, arg1, arg2 });
}

public static String Format(String format, params Object[] args)
{
    // Do work here...
}

那么是否有性能优势,或者这只是为了方便,或者两者兼而有之?在上面的特定情况下,我没有看到任何明显的好处,它似乎只是重复工作。

4

2 回答 2

2

它允许您创建调用该方法的每个签名的委托:

Func<string, object, object> foo = string.Format;

这不适用于params方法;您只能将该重载分配给在其签名Func<string, object[]>中专门提供的委托。params您将被迫创建一个仅调用 params 重载的新方法,以创建示例中使用的签名的委托(可能通过使用 lambda)。

于 2014-09-05T15:51:16.693 回答
1

更新:它不是 String.Concat 而是 String.Format。

我想这背后的原因是所有调用都以 StringBuilder.AppendFormat 结束,这非常复杂,如果您以不同的方式处理每个输入参数的数量,这将是代码重复的主要来源。

如果您有一个重型 API(如跟踪),其中通过参数重载调用方法的开销非常大,情况就不同了。它可以高达 5 倍。隐式委托分配也是如此,这在 LINQ 中很常见。这些临时委托实例在优化代码中并不便宜。例如,Roslyn 禁止使用 LINQ,因为隐式委托分配成本很高。

于 2014-09-05T15:57:34.070 回答