为什么要使用params关键字?

问题描述 投票:310回答:7

我知道这是一个基本问题,但我找不到答案。

为什么要用它?如果你编写一个函数或一个使用它的方法,当你删除它时代码仍然可以完美地工作,100%没有它。例如:

使用params:

static public int addTwoEach(params int[] args)
{
    int sum = 0;
    foreach (var item in args)
        sum += item + 2;
    return sum;
}

没有参数:

static public int addTwoEach(int[] args)
{
    int sum = 0;
    foreach (var item in args)
       sum += item + 2;
    return sum;
}
c# parameter-passing params variadic-functions variadic
7个回答
450
投票

使用params,您可以像这样调用您的方法:

addTwoEach(1, 2, 3, 4, 5);

没有params,你不能。

此外,在以下两种情况下,您都可以使用数组作为参数调用该方法:

addTwoEach(new int[] { 1, 2, 3, 4, 5 });

也就是说,params允许您在调用方法时使用快捷方式。

不相关的,你可以大大缩短你的方法:

public static int addTwoEach(params int[] args)
{
    return args.Sum() + 2 * args.Length;
}

86
投票

使用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

params比较:

static public int addTwoEach(params int[] args)
{
    int sum = 0;

    foreach (var item in args)
    {
        sum += item + 2;
    }

    return sum;
}

addtwoEach(); // returns 0

通常,当参数数量从0到无穷大时,您可以使用参数,并在参数数量从1到无穷大时使用数组。


19
投票

它允许您根据需要在调用中添加任意数量的基本类型参​​数。

addTwoEach(10, 2, 4, 6)

而对于第二种形式,您必须使用数组作为参数

addTwoEach(new int[] {10,2,4,6})

14
投票

params关键字的一个危险是,如果在对方法的调用之后编码,

  1. 某人意外/故意从方法签名中删除一个/多个必需参数,并且
  2. 紧接在params之前的一个/多个必需参数在签名更改之前的参数与params参数类型兼容,

那些调用将继续编译,使用一个或多个以前用于所需参数的表达式作为可选的params参数。我刚遇到了最糟糕的情况:params参数是object[]类型。

这是值得注意的,因为开发人员习惯于编译器拍摄他们的手腕,其中更常见的情况是从具有所有必需参数的方法中删除参数(因为预期的参数数会改变)。

对我来说,这不值得捷径。没有(Type)[]params将使用0到无穷大的参数#而无需覆盖。最糟糕的情况是,您必须在不适用的呼叫中添加, new (Type) [] {}

顺便说一句,imho,最安全(也是最可读的做法)是:

  1. 通过命名参数传递(我们现在甚至可以在C#〜我们可以在VB中使用20年后做到这一点; 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。即使在编写初始呼叫时也可以减轻和减少错误的可能性,更不用说何时必须读取和/或更改呼叫。))

  1. 这样做一个参数 - 每个线路以获得更好的可读性(因为: 2.1。它不那么杂乱,而且 2.2。它避免了必须向右和向后滚动(并且必须这样做PER-LINE,因为大多数凡人都无法读取多行的左侧部分,向右滚动并阅读右侧部分))。 2.3。它与我们已经为分配语句演变的“最佳实践”一致,因为每个传递的参数本质上是一个赋值语句(为本地变量赋值或引用)。就像那些遵循编码风格的最新“最佳实践”的人不会梦想每行编写多个作业语句一样,我们可能不应该(并且不会一次“最佳实践”赶上我的“天才”; P )传递参数时这样做。

笔记:

  1. 在以下情况下传递名称镜像参数的变量无效: 1.1。你传递的是Literal Constants(即简单的0/1,false / true或null,即使是“'Best Practices'”也可能不需要你使用命名常量,因此无法从Method名称中轻易推断出它们的用途) 1.2。该方法比调用者显着更低级别/更通用,因此您不希望/能够将您的变量命名为与参数相同/相似(反之亦然),或者 1.3。您正在重新排序/替换签名中可能导致先前调用仍在编译的参数,因为类型恰好仍然兼容。
  2. 拥有像VS这样的自动换行功能只能消除上面给出的8个原因中的一个(#2.2)。在VS 2015之前,它没有自动缩进(!?!真的,MS?!?),这增加了原因#2.1的严重性。

VS应该有一个生成带有命名参数的方法调用片段的选项(当然每行一个; P)和需要命名参数的编译器选项(在概念上类似于VB中的Option Explicit,顺便说一下,这个需求曾经被认为是同样令人发指,但现在是“'最佳实践'”所要求的。事实上,“在我的日子里回来”;),在1991年我的职业生涯的几个月,甚至在我使用(或者甚至看过)一种带有命名参数的语言之前,我有反对的人/“只是因为你可以,并不意味着你应该“/不要盲目地”削减烤肉的末端“足以模拟它的感觉(使用在线评论),而不会看到任何人这样做。不必使用命名参数(以及保存“'宝贵的'”源代码击键的其他语法)是大多数这些语法开始时Punch Card时代的遗留物。对于现代硬件和IDE以及更复杂的软件而言,没有任何理由可读性更高,更重要。 “代码的阅读频率远高于写入代码”。只要您没有复制非自动更新的代码,当某人(甚至是您自己)稍后尝试阅读时,保存的每次击键都可能成倍增加。


9
投票

无需创建重载方法,只需使用一个带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);

4
投票

params还允许您使用单个参数调用该方法。

private static int Foo(params int[] args) {
    int retVal = 0;
    Array.ForEach(args, (i) => retVal += i);
    return retVal;
}

Foo(1);而不是Foo(new int[] { 1 });。在您可能需要传入单个值而不是整个数组的情况下,对于速记有用。它仍然在方法中以相同的方式处理,但为这种方式调用提供了一些糖果。


4
投票

添加params关键字本身表明,您可以在调用该方法时传递多个参数,这在不使用它的情况下是不可能的。更具体:

static public int addTwoEach(params int[] args)
{
    int sum = 0;

    foreach (var item in args)
    {
        sum += item + 2;
    }

    return sum;
}

当您调用上述方法时,您可以通过以下任何方式调用它:

  1. addTwoEach()
  2. addTwoEach(1)
  3. addTwoEach(new int[]{ 1, 2, 3, 4 })

但是当你删除params关键字时,只有上面给出的第三种方式才能正常工作。对于第一和第二种情况,您将收到错误。

© www.soinside.com 2019 - 2024. All rights reserved.