简体   繁体   English

在C#中同时具有特定参数和params方法重载的好处

[英]Benefits of having both specific arguments and params method overloads in C#

There are a number of examples in the .NET framework where there are multiple overloads for a method, some of which use a specific number of parameters followed by a final "catch all" where the params keyword is used. .NET框架中有许多示例,其中有一个方法有多个重载,其中一些使用特定数量的参数,后跟最后的“catch all”,其中使用了params关键字。 Common examples of this are on the String class eg: 这个例子的常见例子是String类,例如:

I was wondering if there is a particular reason for why there are so many of these method overloads? 我想知道为什么有这么多这些方法重载的特殊原因? At first I thought it might be something to do with performance; 起初我认为这可能与表现有关; the question and answers to this SO question - Cost of using params in C# - would suggest so. 这个问题的问题和答案 - 在C#中使用params的成本 - 就是这样的。

However, I started to delve into the .NET source code using the Reference Source website. 但是,我开始使用Reference Source网站深入研究.NET源代码。 I noticed this in the String class source code : 我在String类源代码中注意到了这一点:

String.Concat() actually runs different code depending on how many fixed arguments are used - this in my mind would definitely be an optimization. String.Concat()实际上运行不同的代码取决于使用了多少固定参数 - 这在我看来肯定是一个优化。 String.Format() however just seems to provide wrappers around the main param method - see below for the paraphrased code: 然而, String.Format()似乎只提供了围绕主param方法的包装器 - 请参阅下面的释义代码:

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...
}

So are there performance benefits or can this simply be a matter of convenience, or maybe both? 那么有性能优势还是仅仅是方便的问题,或者两者兼而有之? In the particular case above I do not see any obvious benefit and it just seems to duplicate work. 在上面的特定情况下,我没有看到任何明显的好处,它似乎只是重复工作。

It allows you to create delegates of each of those signatures that invoke that method: 它允许您创建调用该方法的每个签名的委托:

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

This wouldn't work with a params method; 这不适用于params方法; you could only assign that overload to Func<string, object[]> or a delegate that specifically provided params in its signature. 您只能将该重载分配给Func<string, object[]>或在其签名中专门提供params的委托。 You'd be forced to create a new method that just called the params overload to create a delegate of the signature used int he example (possibly through the use of a lambda). 您将被迫创建一个新方法,该方法只调用params重载来创建一个在他的示例中使用的签名的委托(可能通过使用lambda)。

Update: Its not String.Concat but String.Format. 更新:它不是String.Concat而是String.Format。

I guess the reason behind this is that all calls end up in StringBuilder.AppendFormat which is quite complex and it would be a major source of code duplication if you would handle every number of input arguments in a different way. 我想这背后的原因是所有调用都以StringBuilder.AppendFormat结束,这非常复杂,如果你以不同的方式处理每一个输入参数,它将成为代码重复的主要来源。

Things are different if you have an heavy duty API (like tracing) where the overhead of calling a method via a params overload is very significant. 如果你有一个重型API(如跟踪),通过params重载调用方法的开销非常大,情况会有所不同。 It can be up to a factor of 5. The same goes for implicit delegate allocations which is common with LINQ. 它可以高达5倍。对于LINQ常见的隐式委托分配也是如此。 These temp delegate instances are not cheap in optimized code. 这些临时委托实例在优化代码中并不便宜。 Roslyn for example has banned LINQ usage because of the high implicit delegate allocation costs. 例如,Roslyn禁止使用LINQ,因为隐含的委托分配成本很高。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM