如果你现在在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
方法时,编译器会发出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数组作为参数。