为什么params '性能较差'比普通数组要好

本文关键字:数组 params 性能 为什么 | 更新日期: 2023-09-27 18:03:20

如果你现在在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 '性能较差'比普通数组要好

标题做了一个错误的假设。

参数和非参数方法都接受一个数组;不同之处在于,当调用params方法时,编译器会发出IL来隐式地创建一个数组。数组作为单个参数传递给两个方法。

这可以在这个。net Fiddle中看到(查看"Tidy Up -> view IL")。

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) {}
}

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

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