C# 为什么params';性能较差';而不是常规数组?

C# 为什么params';性能较差';而不是常规数组?,c#,params,variadic-functions,C#,Params,Variadic Functions,如果您现在在IDE中键入string.Format,您将看到有4种不同的重载:一种重载获取字符串和对象,另一种重载获取字符串和两个对象,然后一种重载获取三个对象,最后一种重载使用params。根据,这是因为params生成“开销”,而其他一些语言可能不支持它 我的问题是,为什么像这样的方法调用不能: void Foo() { Bar(1, 2, 3); } void Bar(params int[] args) { // use args... } 基本上在编译时转换为 vo

如果您现在在IDE中键入
string.Format
,您将看到有4种不同的重载:一种重载获取字符串和对象,另一种重载获取字符串和两个对象,然后一种重载获取三个对象,最后一种重载使用
params
。根据,这是因为
params
生成“开销”,而其他一些语言可能不支持它

我的问题是,为什么像这样的方法调用不能:

void Foo()
{
    Bar(1, 2, 3);
}

void Bar(params int[] args)
{
    // use args...
}
基本上在编译时转换为

void Foo()
{
    Bar(new[] { 1, 2, 3 });
}

void Bar(int[] args)
{
    // use args...
}
??这样,除了创建数组(无论如何都是必要的)之外,它不会产生任何开销,并且与其他语言完全兼容


参数的数量在编译时就已经知道了,那么是什么阻止了C#编译器进行某种字符串替换,并使第一种场景基本上成为第二种场景的语法糖呢?为什么我们必须专门实现以支持可变参数?

标题做出了错误的假设

params和non-params方法都采用数组;不同之处在于,编译器将在进行
params
方法调用时发出IL以隐式创建数组。数组作为单个参数传递给这两个方法

这(查看“整理->查看IL”)

在这两种情况下,IL是相同的;将创建一个新数组,填充该数组,并将该数组提供给被调用的方法


这个相同的IL生成有一个“例外”,编译器可以在以非参数形式使用时移出常量值数组,并使用“dup”初始化。但是,在这两种情况下,都会提供一个新数组作为参数。

数组创建是与开销相关的答案。你不能摆脱那项开销。如果使用一个、两个、三个参数提供重载,那么当使用少于4个项调用数组时,就不需要进行数组分配了。@MarcinJuraszek如果你看看这个问题,似乎非
params
string.Format
重载只需在创建新数组后调用
params
即可。内存开销不是这里唯一的问题-创建数组并用项目填充它会在方法中生成额外的IL,这使得它不太可能被JIT内联。这只是猜测,但是,如果编译器知道一个方法只接受n个参数而不是可变数量的参数,它可能能够更好地优化代码的性能,例如将变量存储在寄存器中,而不必创建数组。@Matthew和MarcinJuraszek,如果代码只调用一个方法来执行您试图避免的操作,那么优化/内联代码有什么意义?创建一个数组,用3个元素填充它,并将其传递给
params
重载?谢谢,这是一个非常好的答案-但是如果
params int[]
int[]
完全相同,那么为什么不能调用
参数int[]
?@JamesKo这将是当前特定语言本身的设计限制。在这些情况下,他们可以显式指定数组,或者可能调用一个N参数重载。是的,但是如果
params
只是编译时的事情,那么他们不应该能够传入普通数组吗?@JamesKo是的,他们应该能够。但是,如果语言支持重载(而且必须使用CLR/.NET),那么即使不知道
params
-行为,对于1..4个参数,它仍然可以“像varargs一样工作”。(我只使用支持params的C#和VB.NET,我不知道有哪种语言不支持params。)
using System;

public class Program
{
    public static void Main()
    {
        var a1 = 1;
        var a2 = 2;
        var a3 = 3; 
        with_params(a1,a2,a3);
        no_params(new [] {a1,a2,a3});
    }

    public static void with_params(params int[] x) {}
    public static void no_params(int[] x) {}
}