357

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

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

带参数:

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;
}
4

11 回答 11

508

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;
}
于 2011-09-28T08:24:23.890 回答
101

Usingparams允许您在没有参数的情况下调用函数。没有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 到无穷大时可以使用 params,而当参数的数量可以从 1 到无穷大时使用数组。

于 2011-09-28T09:05:13.717 回答
22

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

addTwoEach(10, 2, 4, 6)

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

addTwoEach(new int[] {10,2,4,6})
于 2011-09-28T08:26:06.013 回答
21

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

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

这些调用将继续使用一个/多个以前用于所需参数的表达式进行编译,这些参数被视为可选params参数。我刚刚遇到了最坏的情况:paramsParameter 是 Type object[]

这是值得注意的,因为开发人员已经习惯了编译器在更常见的情况下用所有必需参数从方法中删除参数(因为预期的参数数量会改变)。

对我来说,不值得走捷径。 (Type)[]withoutparams将与 0 到无穷大的参数一起工作,而无需覆盖。最坏的情况是您必须, new (Type) [] {}在不适用的呼叫中添加一个。

顺便说一句,恕我直言,最安全(也是最易读的做法)是:

  1. 通过命名参数传递(我们现在甚至可以在 C# 中做到这一点,比我们在 VB 中可以做到的大约 2;P),因为:

    1.1。这是保证防止在参数顺序、兼容类型和/或调用编码后计数更改后传递给参数的意外值的唯一方法,

    1.2. 它减少了参数含义更改后的这些机会,因为反映新含义的可能新标识符名称就在传递给它的值旁边,

    1.3. 它避免了必须计算逗号并从调用到签名来回跳转以查看正在为什么参数传递什么表达式,以及

    1.3.1。顺便说一句,仅此一个原因就足够了(就避免频繁容易出错的 DRY 原则而言,只是阅读代码更不用说修改它了),但是如果有一个/更多被传递的表达式本身包含逗号,即多维数组引用或多参数函数调用。在这种情况下,您甚至不能使用(即使可以,仍然会为每个方法调用的每个参数添加一个额外的步骤)在编辑器的选择中查找所有出现的功能来自动为您计算逗号。

    1.4. 如果您必须使用可选参数(params或不使用),它允许您搜索通过特定可选参数的调用(因此,很可能不是或至少有可能不是默认值),

(注意:原因 1.2. 和 1.3. 可以减轻和减少错误的机会,即使是在对初始调用进行编码时,更不用说何时必须读取和/或更改调用。))

  1. 这样做 ONE - PARAMETER - PER - LINE 以获得更好的可读性(因为:

    2.1。它不那么混乱,并且

    2.2. 它避免了必须向右和向左滚动(并且必须每行都这样做,因为大多数凡人无法阅读多行的左侧部分,向右滚动并阅读右侧部分))。

    2.3. 它与我们已经演变成的赋值语句的“最佳实践”一致,因为传递的每个参数本质上都是一个赋值语句(将值或引用分配给局部变量)。就像那些遵循编码风格中最新“最佳实践”的人不会梦想每行编写多个作业语句一样,我们可能不应该(一旦“最佳实践”赶上我的“天才”,也不会;P ) 在传递参数时这样做。

注意事项

  1. 在以下情况下,传入名称反映“参数”的变量无济于事:

    1.1。您正在传递字面常量(即简单的 0/1、false/true 或 null,即使是“最佳实践”也可能不需要您使用命名常量,并且无法从方法名称中轻松推断出它们的目的),

    1.2. 该方法比调用者明显更低级别/更通用,因此您不希望/能够将变量命名为与参数相同/相似(反之亦然),或者

    1.3. 您正在重新排序/替换签名中的参数,这可能导致先前的调用仍在编译,因为类型碰巧仍然兼容。

  2. 拥有像 VS 这样的自动换行功能只会消除我上面给出的 8 个原因中的一个(#2.2)。在 VS 2015 之前,它没有自动缩进(!?!真的,MS?!?)这增加了原因 #2.2 的严重性。

VS 应该有一个选项可以生成带有命名参数的方法调用片段(当然每行一个;P)和一个需要命名参数的编译器选项(在概念上类似于 VB 中的 Option Explicit,顺便说一句,曾经认为这个要求很简单同样令人发指,但现在是“最佳实践”所要求的)。事实上,“回到我的day" ;),在 1991 年,我的职业生涯刚刚开始几个月,甚至在我使用(或什至见过)带有命名参数的语言之前,我就有了 anti-sheeple /“只是因为你可以,并不意味着你应该” /不要盲目地“切断烤肉”的感觉来模拟它(使用内嵌注释)而没有看到任何人这样做。不必使用命名参数(以及其他节省“珍贵”的语法源代码击键)是大多数这些语法开始时打孔卡时代的遗物。现代硬件和 IDE 以及可读性非常、非常、非常复杂的更复杂的软件没有任何借口更重要。“阅读代码的频率远高于编写代码的频率”。只要您不复制非自动更新的代码,当有人(甚至您自己)稍后尝试阅读它时,保存的每次击键都可能会成倍增加成本。

于 2015-06-30T18:05:32.077 回答
10

无需创建重载方法,只需使用一个带参数的方法,如下所示

// 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);
于 2014-03-31T07:43:42.140 回答
5

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 });. 在您可能需要传入单个值而不是整个数组的情况下,这对于速记很有用。它仍然在方法中以相同的方式处理,但为以这种方式调用提供了一些糖果。

于 2011-09-28T08:55:44.317 回答
5

添加 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 关键字时,只有上述给定方式的第三种方式才能正常工作。对于第一种和第二种情况,您将收到错误消息。

于 2014-01-18T09:12:54.403 回答
1

需要强调一件更重要的事情。它更好用params,因为它对性能更好。当您调用带有params参数的方法并没有传递给它时:

public void ExampleMethod(params string[] args)
{
// do some stuff
}

称呼:

ExampleMethod();

然后新版本的 .Net Framework 执行此操作(来自 .Net Framework 4.6):

ExampleMethod(Array.Empty<string>());

这个Array.Empty对象以后可以被框架重用,所以不需要做多余的分配。当您像这样调用此方法时,将发生这些分配:

 ExampleMethod(new string[] {});
于 2019-07-14T09:52:38.150 回答
0

可能听起来很愚蠢,但 Params 不允许多维数组。而您可以将多维数组传递给函数。

于 2019-12-01T17:20:47.770 回答
0

另一个例子

public IEnumerable<string> Tokenize(params string[] words)
{
  ...
}

var items = Tokenize(product.Name, product.FullName, product.Xyz)
于 2019-12-03T00:05:06.133 回答
0

它增强了简洁性。当你可以快速时,为什么要传统?

using System;

namespace testingParams
{
    class Program
    {
        private void canOnlyBeCalledSlowly(int[] myArr)
        {
            Console.WriteLine("Snore");
        }
        private void canBeCalledQuickly(params int[] myArr) {
            Console.WriteLine("That was quick");
        }

        static void Main(string[] args)
        {
            Program p = new Program();
            //We're being conventional here:
            int[] myArr = new int[] { 1, 2, 3, 4, 5 };
            p.canOnlyBeCalledSlowly(myArr);
            //We're being quick here:
            p.canBeCalledQuickly(1, 2, 3);
        }
    }
}
于 2021-05-01T23:46:28.030 回答