我最近了解到,你可以创建一些具有无限参数的方法,例如:
SomeMethod(params int[] numbers);
但我的问题是,这和仅仅创建一个接收列表或数组的方法有什么区别?
SomeMethod(int[] numbers);
SomeMethod(List<int> numbers);
也许它对性能有一些影响?我不完全理解或看到您更喜欢具有无限参数的那个。
在谷歌上快速搜索没有帮助,我希望你能帮助我。
这和仅仅创建一个接收列表或数组的方法有什么区别?
两者之间的区别
void M(params int[] x)
和
void N(int[] x)
是M可以这样称呼:
M(1, 2, 3)
或者像这样:
M(new int[] { 1, 2, 3 });
但 N 只能以第二种方式调用,而不是第一种方式。
也许它对性能有一些影响?
对性能的影响在于,无论以第一种方式还是第二种方式调用M
,无论哪种方式都会创建数组。创建阵列会影响性能,因为它需要时间和内存。请记住,应根据性能目标来衡量性能影响;创建额外阵列的成本不太可能是市场上成功与失败之间区别的门控因素。
我不完全理解或看到您更喜欢具有无限参数的那个。
对于调用该方法的代码的作者来说,这纯粹是一种方便;它只是更短,更容易编写。
M(1, 2, 3);
而不是写作
M(new int[] { 1, 2, 3 });
它只是在呼叫者端节省了几次击键。仅此而已。
您没有问但可能想知道答案的几个问题:
这个功能叫什么?
允许在调用方传递可变数量的参数的方法称为可变参数。参数方法是 C# 实现可变参数方法的方式。
过载分辨率如何与可变参数方法一起工作?
当遇到重载解决问题时,C# 将同时考虑"正常"和"扩展"形式,如果两者都适用,则"正常"形式始终获胜。 例如,考虑一下:
void P(params object[] x){}
我们有一个电话
P(null);
有两种适用的可能性。在"正常"形式中,我们调用P
并为数组传递空引用。在"扩展"形式中,我们称之为P(new object[] { null })
. 在这种情况下,正常形式获胜。 如果我们有一个调用P(null, null)
那么普通表单不适用,默认情况下扩展表单获胜。
挑战:假设我们有var s = new[] { "hello" };
和呼叫P(s);
。 描述呼叫站点发生的情况及其原因。你可能会感到惊讶!
挑战:假设我们既有void P(object x){}
,又有void P(params object[] x){}
。P(null)
做什么,为什么?
挑战:假设我们既有void M(string x){}
,又有void M(params string[] x){}
。M(null)
做什么,为什么?这与前一个案例有何不同?
只是做了一个小原型。答案似乎是params
只是用于在数组中传递的语法糖。这并不奇怪。我创建了同一方法的两个版本,唯一的区别是"params"关键字。为两者生成的 IL 是相同的,只是System.ParamArrayAttribute
应用于params
版本。
此外,在调用站点生成的 IL 在我使用手动声明的new int[]
调用方法与仅使用params
参数调用该方法之间也是相同的。
所以,答案似乎是"方便"。性能似乎没有任何差异。你也可以用数组调用params
函数,所以这也就不足为奇了。归根结底,方法的使用者是否更容易使用任意数量的参数调用它(例如someMethod(1, 2, 3)
) 而不是总是必须首先创建一个集合(例如someMethod(new List<int>() { 1, 2, 3 } )
)。
无限参数的功能在许多情况下具有以下优势:
- 松耦合
- 增强的可重用性
- 更好的应用程序整体性能
下面是一个示例,其中无限参数选项是一个不错的选择
考虑需要构建用于发送电子邮件的应用程序。
发送电子邮件的函数必须能够处理"收件人"、"抄送"和"密件抄送"字段的单个或多个值。
如果参数类型固定为所有字段(收件人、抄送、密件抄送)的数组或列表,则调用函数将被迫处理定义 3 个数组或列表的所有复杂性,以便调用电子邮件发件人函数。
即使调用方只想向一个地址发送电子邮件,电子邮件发送器函数也会强制调用方定义并发送 3 个不同的数组作为参数。
如果电子邮件发送方函数采用无限参数方法,则调用方函数不需要处理所有的复杂性。
无限参数方法通过避免在不必要的位置创建数组或列表,有助于提高应用程序的运行时性能。
从非性能、样式的角度来看,当您想要发送可选的参数列表时,params
关键字非常好。
就个人而言,当我的代码是这样的时,我会使用params
SomeMethod('Option1', 'Option17');
void SomeMethod(params string[] options)
{
foreach(var option in options)
{
switch(option): ...
}
}
这样做的好处是我可以到处使用此方法,而不必每次都创建数组或列表。
当我知道我将始终向此函数传递一组已经放在一起的数据时,我会使用array
或list
List<User> users = GetUsersFromDB();
SomeMethod(users);
我看到了params
的好处在于它增加了灵活性。它可能对你的代码影响相对较小,但它仍然是一个很好的工具。
调用约定不同。 例如。。。
public class Test
{
public void Method1( params int[] nums )
{
nums.ToList().ForEach( n => Console.WriteLine(n) );
}
public void Method2( List<int> nums )
{
nums.ForEach( n => Console.WriteLine(n) );
}
}
void Main()
{
var t = new Test();
t.Method1( 1, 2, 3, 4 );
t.Method2( new List<int>() { 1, 2, 3, 4 } );
}
在第一种情况下,可以将任意数量的整数作为单独的参数传递给方法。 在第二个中,您需要实例化一个列表并传递它。