为什么要使用params关键字?

本文翻译自:Why use the params keyword?

I know this is a basic question, but I couldn't find an answer. 我知道这是一个基本问题,但我找不到答案。

Why use it? 为什么要使用它? if you write a function or a method that's using it, when you remove it the code will still work perfectly, 100% as without it. 如果编写使用该函数的方法或方法,则将其删除时代码仍将完美运行,没有代码的情况下100%正常运行。 Eg: 例如:

With params: 有参数:

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

Without params: 没有参数:

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

#1楼

参考:https://stackoom.com/question/VnyX/为什么要使用params关键字


#2楼

Adding params keyword itself shows that you can pass multiple number of parameters while calling that method which is not possible without using it. 添加params关键字本身表明您可以在调用该方法时传递多个参数,如果不使用它,则无法实现。 To be more specific: 更加具体:

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

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

    return sum;
}

When you will call above method you can call it by any of the following ways: 当您调用上述方法时,可以通过以下任何一种方法来调用它:

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

But when you will remove params keyword only third way of the above given ways will work fine. 但是,当您删除params关键字时,只有上述方法中的第三种方法可以正常工作。 For 1st and 2nd case you will get an error. 对于第一种和第二种情况,您将得到一个错误。


#3楼

No need to create overload methods, just use one single method with params as shown below 无需创建重载方法,只需使用一个带有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楼

One danger with params Keyword is, if after Calls to the Method have been coded, 使用params关键字的一种危险是,如果对方法的调用进行编码之后,

  1. someone accidentally / intentionally removes one/more required Parameters from the Method Signature, and 有人不小心/有意从方法签名中删除了一个/多个必需的参数,并且
  2. one/more required Parameters immediately prior to the params Parameter prior to the Signature change were Type-Compatible with the params Parameter, 一个或多个必需的参数,紧接在params参数之前的参数与params Parameter类型兼容,

those Calls will continue to compile with one/more Expressions previously intended for required Parameters being treated as the optional params Parameter. 这些调用将继续使用先前用于必需参数的一个/多个表达式进行编译,这些表达式被视为可选的params参数。 I just ran into the worst possible case of this: the params Parameter was of Type object[] . 我只是遇到了最糟糕的情况: params Parameter是Type object[]

This is noteworthy because developers are used to the compiler slapping their wrists with the much, much more common scenario where Parameters are removed from a Method with all required Parameters (because the # of Parameters expected would change). 这是值得注意的,因为开发人员已经习惯了编译器以更为常见的场景拍手,其中从具有所有必需参数的方法中删除参数(因为预期的参数数量会发生变化)。

For me, it's not worth the shortcut. 对我而言,这不值得捷径。 (Type)[] without params will work with 0 to infinity # of Parameters without needing Overrides. 不带params (Type)[]可以使用0到无穷大数量的参数,而无需覆盖。 Worst case is you'll have to add a , new (Type) [] {} to Calls where it doesn't apply. 最坏的情况是,您必须在不适用的Calls中添加一个, new (Type) [] {}

Btw, imho, the safest (and most readable practice) is to: 顺便说一句,恕我直言,最安全(也是最易读的做法)是:

  1. pass via Named Parameters (which we can now do even in C# ~2 decades after we could in VB ;P) (because: 通过命名参数传递(我们现在甚至可以在C#做〜2个后, 几十年来我们可以在VB; P)(这是因为:

    1.1. 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, 这是唯一的方法,可以确保防止在对参数进行顺序编码,对Compatible-Type和/或计数进行编码后更改了传递给Parameters的意外值之后,

    1.2. 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. 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 它避免了必须计算逗号并从Call to Signature来回跳转,以查看为什么参数传递了什么Expression,以及

    1.3.1. 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, ie Multi-Dimensional Array Refs or Multi-Parameter Function Calls. 顺便说一句,仅仅因为这个原因应该是充足的 (以避免频繁出错违反了DRY原则的只是阅读代码更何况还修改而言),但如果有一个这样的原因可能是成倍更重要的/更多传递的表达式本身包含逗号,即多维数组引用或多参数函数调用。 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. 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), 如果必须使用可选参数( params与否),它可以让你搜索,其中一个特定的可选参数传递调用(因此,最有可能的是没有或者至少有被没有默认值的可能性),

(NOTE: Reasons 1.2. and 1.3. can ease and reduce chances of error even on coding the initial Calls not to mention when Calls have to be read and/or changed.)) (注意:原因1.2和1.3可以缓解并减少出错的机会,即使在对初始Call进行编码时,更不用说在必须读取和/或更改Call的情况下了。)

and

  1. do so ONE - PARAMETER - PER - LINE for better readability (because: 这样做-参数-每行-以获得更好的可读性(因为:

    2.1. 2.1。 it's less cluttered, and 它不那么混乱,并且

    2.2. 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. 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. 就像那些遵循最新的 “最佳实践”编码风格的人不会梦想每行编码多个赋值语句一样,我们可能不应该(而且“最佳实践”不会赶上我的“天才”; P )在传递参数时执行此操作。

NOTES : 注意事项

  1. Passing in Variables whose names mirror the Parameters' doesn't help when: 在以下情况下,传递名称与“参数”相对应的变量无济于事:

    1.1. 1.1。 you're passing in Literal Constants (ie 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), 您传入的是文字常量(即简单的0/1,false / true或null,即使“'最佳实践'”也可能不需要您使用命名常量,并且无法轻易地从方法名称中推断出它们的用途) ),

    1.2. 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. 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. 您正在重新排序/替换签名中的参数,这可能导致先前的调用仍在编译中,因为类型恰好仍然兼容。

  2. Having an auto-wrap feature like VS does only eliminates ONE (#2.2) of the 8 reasons I gave above. 拥有像VS这样的自动换行功能并不能消除我上面给出的8个原因中的一个(#2.2)。 Prior to as late as VS 2015, it did NOT auto-indent (!?! Really, MS?!?) which increases severity of reason #2.1. 在VS 2015之前,它没有自动缩进(!?!确实是MS?!?),这会增加原因#2.1的严重性。

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'"). VS应该有一个选项,该选项生成带有命名参数的方法调用摘要(每行当然一个; P),以及一个需要命名参数的编译器选项(概念上与VB中的Option Explicit类似,顺便说一句,对需求的要求很容易想到)同样令人发指,但现在“最佳做法”确实要求这样做 )。 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. 事实上,“早在我的一天”),于1991年就在几个月到我的职业生涯中,我用之前也(或者甚至已经看到的)语言与命名参数,我不得不防sheeple /“只是因为你可以,并不意味着您应该” /不要盲目地“削减烤肉的末端”的感觉,以模拟它(使用内联注释),而没有看到任何人这样做。 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. 当大多数语法开始使用时,不必使用命名参数(以及其他保存“'precious””源代码击键的语法)。 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. 有没有借口,与现代的硬件和IDE的和更复杂的软件,其中的可读性是很多,很多,重要得多 "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. 只要您不复制非自动更新的代码,当有人(甚至您自己)以后尝试阅读它时,保存的每个击键都可能成倍增加成本。


#5楼

One more important thing needs to be highlighted. 还需要强调一件事。 It's better to use params because it is better for performance. 使用params更好,因为它对性能更好。 When you call a method with params argument and passed to it nothing: 当您使用params参数调用方法并没有传递给它时:

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

call: 呼叫:

ExampleMethod();

Then a new versions of the .Net Framework do this (from .Net Framework 4.6): 然后,新版本的.Net Framework会执行此操作(来自.Net Framework 4.6):

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

This Array.Empty object can be reused by framework later, so there are no needs to do redundant allocations. Array.Empty对象可以在以后由框架重用,因此无需进行冗余分配。 These allocations will occur when you call this method like this: 当您这样调用此方法时,将发生这些分配:

 ExampleMethod(new string[] {});

#6楼

Might sound stupid, But Params doesn't allow multidimensional array. 听起来可能很愚蠢,但是Params不允许多维数组。 Whereas you can pass a multidimensional array to a function. 而您可以将多维数组传递给函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值