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

为什么要用它?如果你编写的函数或方法正在使用它,当你删除它时,代码仍然可以完美地工作,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;
}

当前回答

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

有人不小心/故意地从方法签名中删除一个/多个必需的参数, 而且 在签名更改之前,一个/多个必需的参数与params参数类型兼容。

这些调用将继续编译一个/多个表达式,这些表达式之前用于必要的参数被视为可选的参数参数。我只是遇到了最糟糕的情况:params参数的类型是对象[]。

这一点是值得注意的,因为开发人员已经习惯了编译器在更常见的情况下把参数从一个方法中删除(因为期望的参数#会改变)。

对我来说,不值得抄近路。(类型)[]没有参数将工作在0到无穷大#参数,而不需要覆盖。最坏的情况是,你将不得不添加一个,new (Type)[]{}到不适用的调用。

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

pass via Named Parameters (which we can now do even in C# ~2 decades after we could in VB ;P), because: 1.1. it's the only way that guarantees prevention of unintended values passed to Parameters after Parameter order, Compatible-Type and/or count change after Calls have been coded, 1.2. it reduces those chances after a Parameter meaning change, because the likely new identifier name reflecting the new meaning is right next to the value being passed to it, 1.3. it avoids having to count commas and jump back & forth from Call to Signature to see what Expression is being passed for what Parameter, and 1.3.1. By the way, this reason alone should be plenty (in terms of avoiding frequent error-prone violations of the DRY Principle just to read the code not to mention also modify it), but this reason can be exponentially more important if there are one/more Expressions being Passed that themselves contain commas, i.e. Multi-Dimensional Array Refs or Multi-Parameter Function Calls. In that case, you couldn't even use (which even if you could, would still be adding an extra step per Parameter per Method Call) a Find All Occurrences in a Selection feature in your editor to automate the comma-counting for you. 1.4. if you must use Optional Parameters (params or not), it allows you to search for Calls where a particular Optional Parameter is Passed (and therefore, most likely is not or at least has the possibility of being not the Default Value),

(注:原因1.2.;和1.3。可以减轻和减少错误的机会,甚至在编码初始调用时,更不用说当调用必须读取和/或更改时。))

and

do so ONE - PARAMETER - PER - LINE for better readability (because: 2.1. it's less cluttered, and 2.2. it avoids having to scroll right & back left (and having to do so PER - LINE, since most mortals can't read the left part of multiple lines, scroll right and read the right part)). 2.3. it's consistent with the "Best Practice" we've already evolved into for Assignment Statements, because every Parameter Passed is in essence an Assignment Statement (assigning a Value or Reference to a Local Variable). Just like those who follow the latest "Best Practice" in Coding Style wouldn't dream of coding multiple Assignment Statements per line, we probably shouldn't (and won't once "Best Practice" catches up to my "genius" ;P ) do so when Passing Parameters.

注:

Passing in Variables whose names mirror the Parameters' doesn't help when: 1.1. you're passing in Literal Constants (i.e. a simple 0/1, false/true or null that even "'Best Practices'" may not require you use a Named Constant for and their purpose can't be easily inferred from the Method name), 1.2. the Method is significantly lower-level / more generic than the Caller such that you would not want / be able to name your Variables the same/similar to the Parameters (or vice versa), or 1.3. you're re-ordering / replacing Parameters in the Signature that may result in prior Calls still Compiling because the Types happen to still be compatible. Having an auto-wrap feature like VS does only eliminates ONE (#2.2) of the 8 reasons I gave above. Prior to as late as VS 2015, it did NOT auto-indent (!?! Really, MS?!?) which increases severity of reason #2.2.

VS should have an option that generates Method Call snippets with Named Parameters (one per line of course ;P) and a compiler option that requires Named Parameters (similar in concept to Option Explicit in VB which, btw, the requirement of was prolly once thought equally as outrageous but now is prolly required by "'Best Practices'"). In fact, "back in my day" ;), in 1991 just months into my career, even before I was using (or had even seen) a language with Named Parameters, I had the anti-sheeple / "just cuz you can, don't mean you should" / don't blindly "cut the ends of the roast" sense enough to simulate it (using in-line comments) without having seen anyone do so. Not having to use Named Parameters (as well other syntax that save "'precious'" source code keystrokes) is a relic of the Punch Card era when most of these syntaxes started. There's no excuse for that with modern hardware and IDE's and much more complex software where readability is much, Much, MUCH more important. "Code is read much more often than is written". As long as you're not duplicating non-auto-updated code, every keystroke saved is likely to cost exponentially more when someone (even yourself) is trying to read it later.

其他回答

使用参数你可以像这样调用你的方法:

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

如果没有参数,就不能。

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

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

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

与此无关,你可以大大缩短你的方法:

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

使用参数可以不带参数地调用函数。无参数:

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

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

    return sum;
}

addtwoEach(); // throws an error

与参数比较:

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到无穷大时,可以使用数组。

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

还有一件重要的事情需要强调。最好使用参数,因为它的性能更好。当你调用一个带有params参数的方法时,什么都没有传递给它:

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

电话:

ExampleMethod();

然后。net Framework的新版本(从。net Framework 4.6开始):

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

这个数组。空对象以后可以被框架重用,所以不需要做多余的分配。这些分配将在你像这样调用这个方法时发生:

 ExampleMethod(new string[] {});

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

// 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);