Mas*_*tic 326 c# variadic parameter-passing variadic-functions params
我知道这是一个基本问题,但我找不到答案.
为什么要用它?如果你编写一个函数或一个使用它的方法,当你删除它时代码仍然可以正常工作,100%没有它.例如:
使用params:
static public int addTwoEach(params int[] args)
{
int sum = 0;
foreach (var item in args)
sum += item + 2;
return sum;
}
Run Code Online (Sandbox Code Playgroud)
没有参数:
static public int addTwoEach(int[] args)
{
int sum = 0;
foreach (var item in args)
sum += item + 2;
return sum;
}
Run Code Online (Sandbox Code Playgroud)
Kon*_*lph 470
有了params你可以打电话给你的方法是这样的:
addTwoEach(1, 2, 3, 4, 5);
Run Code Online (Sandbox Code Playgroud)
没有params,你不能.
此外,在以下两种情况下,您都可以使用数组作为参数调用该方法:
addTwoEach(new int[] { 1, 2, 3, 4, 5 });
Run Code Online (Sandbox Code Playgroud)
也就是说,params允许您在调用方法时使用快捷方式.
不相关的,你可以大大缩短你的方法:
public static int addTwoEach(params int[] args)
{
return args.Sum() + 2 * args.Length;
}
Run Code Online (Sandbox Code Playgroud)
Vas*_*sya 91
使用params允许您调用没有参数的函数.没有params:
static public int addTwoEach(int[] args)
{
int sum = 0;
foreach (var item in args)
{
sum += item + 2;
}
return sum;
}
addtwoEach(); // throws an error
Run Code Online (Sandbox Code Playgroud)
比较params:
static public int addTwoEach(params int[] args)
{
int sum = 0;
foreach (var item in args)
{
sum += item + 2;
}
return sum;
}
addtwoEach(); // returns 0
Run Code Online (Sandbox Code Playgroud)
通常,当参数数量从0到无穷大时,您可以使用参数,并在参数数量从1到无穷大时使用数组.
okr*_*now 22
它允许您根据需要在调用中添加任意数量的基本类型参数.
addTwoEach(10, 2, 4, 6)
Run Code Online (Sandbox Code Playgroud)
而对于第二种形式,您必须使用数组作为参数
addTwoEach(new int[] {10,2,4,6})
Run Code Online (Sandbox Code Playgroud)
Tom*_*Tom 16
params关键字的一个危险是,如果在调用方法之后编码,
params签名更改之前的参数之前与params参数类型兼容,那些调用将继续编译,其中一个或多个表达式以前用于将所需参数视为可选params参数.我刚遇到了最糟糕的情况:params参数是Type object[].
这是值得注意的,因为开发人员习惯于编译器拍摄他们的手腕,其中更常见的情况是从具有所有必需参数的方法中删除参数(因为预期的参数数会改变).
对我来说,这不值得捷径. (Type)[]无需params使用0到无穷大的参数#,无需覆盖.最糟糕的情况是你必须, new (Type) [] {}在不适用的地方添加一个Call.
顺便说一句,imho,最安全(也是最可读的做法)是:
通过命名参数(这是我们现在可以做通,甚至在C#〜2个几十年我们可以在VB后; P)(这是因为:
1.1.它是保证在调用Calls之后参数顺序,Compatible-Type和/或计数更改后防止传递给Parameters的非预期值的唯一方法,
1.2.它会减少参数意义改变后的机会,因为反映新含义的新标识符名称就在传递给它的值的旁边,
1.3.它避免了必须计算逗号并从Call to Signature中来回跳转以查看正在传递什么参数的表达式,以及
1.3.1.顺便说一下,这个原因应该是充足的(就避免频繁出错的违反DRY原则而言只是为了阅读代码而不仅仅是修改它),但如果有一个/那么这个原因可以指数地更重要/传递的表达式本身包含逗号,即多维数组引用或多参数函数调用.在这种情况下,您甚至无法使用(即使您可以,仍然会为每个方法调用的每个参数添加一个额外的步骤)在编辑器中的"选择"功能中查找所有事件,以自动为您进行逗号计数.
1.4.如果你必须使用可选参数(params或不使用),它允许你搜索特定可选参数被传递的呼叫(因此,很可能不是或至少有可能不是默认值),
(注意:原因1.2.和1.3.即使在编写初始呼叫时也可以减轻和减少错误的可能性,更不用说何时必须读取和/或更改呼叫.))
和
这样做一个参数 - 每个线路以获得更好的可读性(因为:
2.1.它不那么杂乱,而且
2.2.它避免了必须向右和向后滚动(并且必须这样做PER-LINE,因为大多数凡人都无法读取多行的左侧部分,向右滚动并阅读右侧部分)).
2.3.它与我们已经为分配语句演变的"最佳实践"一致,因为每个传递的参数本质上是一个赋值语句(为本地变量赋值或引用).就像那些遵循编码风格的最新 "最佳实践"的人不会梦想每行编写多个作业语句一样,我们可能不应该(并且不会一次"最佳实践" 赶上我的"天才"; P )传递参数时这样做.
注意:
在以下情况下传递名称镜像参数的变量无效:
1.1.你传递的是Literal Constants(即简单的0/1,false/true或null,即使是"'Best Practices'"也可能不需要你使用命名常量,因此无法从Method名称中轻易推断出它们的用途)
1.2.该方法比调用者显着更低级别/更通用,因此您不希望/能够将您的变量命名为与参数相同/相似(反之亦然),或者
1.3.您正在重新排序/替换签名中可能导致先前调用仍在编译的参数,因为类型恰好仍然兼容.
拥有像VS这样的自动换行功能只能消除上面给出的8个原因中的一个(#2.2).在VS 2015之前,它没有自动缩进(!?!真的,MS?!?),这增加了原因#2.1的严重性.
VS应该有一个生成带有命名参数的方法调用片段的选项(当然每行一个; P)和需要命名参数的编译器选项(在概念上类似于VB中的Option Explicit,顺便说一下,这个需求曾经被认为是同样的离谱,但现在prolly 需要通过"'最佳实践’").事实上,"在我的日子里回来";),1991年我职业生涯的几个月,甚至在我使用(或者甚至看过)一种带有命名参数的语言之前,我就有了反对的人/"只是因为你可以,并不意味着你应该"/不要盲目地"削减烤肉的末端"足以模拟它的感觉(使用在线评论),而不会看到任何人这样做.不必使用命名参数(以及保存"'宝贵的'"源代码击键的其他语法)是大多数这些语法开始时Punch Card时代的遗留物.有没有借口,与现代的硬件和IDE的和更复杂的软件,其中的可读性是很多,很多,MUCH更重要."代码的阅读频率远高于写入代码".只要您没有复制非自动更新的代码,当某人(甚至是您自己)稍后尝试阅读时,保存的每次击键都可能成倍增加.
ele*_*bah 10
无需创建重载方法,只需使用一个带params的方法,如下所示
// Call params method with one to four integer constant parameters.
//
int sum0 = addTwoEach();
int sum1 = addTwoEach(1);
int sum2 = addTwoEach(1, 2);
int sum3 = addTwoEach(3, 3, 3);
int sum4 = addTwoEach(2, 2, 2, 2);
Run Code Online (Sandbox Code Playgroud)
params 还允许您使用单个参数调用该方法。
private static int Foo(params int[] args) {
int retVal = 0;
Array.ForEach(args, (i) => retVal += i);
return retVal;
}
Run Code Online (Sandbox Code Playgroud)
即Foo(1);而不是Foo(new int[] { 1 });. 在您可能需要传入单个值而不是整个数组的情况下,这对于速记很有用。它仍然在方法中以相同的方式处理,但为这种方式调用提供了一些糖果。
小智 5
添加params关键字本身表明您可以在调用该方法的同时传递多个参数,如果不使用它,则无法实现。更加具体:
static public int addTwoEach(params int[] args)
{
int sum = 0;
foreach (var item in args)
{
sum += item + 2;
}
return sum;
}
Run Code Online (Sandbox Code Playgroud)
当您调用上述方法时,可以通过以下任何一种方法来调用它:
addTwoEach()addTwoEach(1)addTwoEach(new int[]{ 1, 2, 3, 4 })但是,当您删除params关键字时,只有上述方法中的第三种方法可以正常工作。对于第一种和第二种情况,您将得到一个错误。