为什么C#允许在集合初始化器中使用尾随逗号,但不允许在params中使用?

20

有效的语法:

var test = new List<string>
{
   "a",
   "b",
   "c",//Valid trailing comma
};

语法无效:

private void Test(params string[] args)
{
}

Test(
   "a",
   "b",
   "c",//Invalid trailing comma
);

这是语法不一致还是经过计算的决定?


在第二个例子中,编译器使用逗号来分隔方法参数,而不是集合项。params被单独处理。在方法参数上,您从未能够留下尾随逗号。 - Adam Houldsworth
1
编译器不是人,它不知道也不关心你想将集合传递给方法。它只是“看到”语法无效。前一种语法是有效的,因为在语言规范中允许初始化集合。 - Tim Schmelter
3
这个问题被错误地关闭为重复。链接的问题回答了“为什么我们允许在集合初始化器上使用尾随逗号”,而这个问题是在问“为什么我们不允许在params方法参数上使用尾随逗号”。话虽如此,答案可能会相似 - 但问题并不相同。 - Adam Houldsworth
区别在于使用或不使用 params 时方法调用看起来相同。从技术上讲,这可能是可行的,但是 params 和初始化程序是后来添加的。 - BartoszKP
2
这就是为什么在第一种情况下允许逗号的原因: https://dev59.com/d3I95IYBdhLWcg3wzRTv#2147344我认为区别在于当初始化列表时,您正在列出相同类型的元素,但是在调用函数时,您可以在那里放置任何东西,因此语法要严格得多。 - Andrew
显示剩余3条评论
2个回答

13
所以,尽管我不是编译器团队的一员,并且“真正”的原因可能不得而知,但我还是会试着解释一下这个问题-并且这个问题是否存在仍有疑问。
在几个场景中,尾随逗号通常很有用,即合并和代码生成。在集合或属性初始化程序和枚举等内容的上下文中,保留尾随逗号是无害的(编译器可以安全地推断“列表结束”,因为它还有一个可挂钩的闭合块括号)。
方法参数非常明确-编译器需要在这个领域提供很多控制,以便在人们编写代码时提供良好的反馈和其他辅助功能。在方法参数上保留尾随逗号不会增加任何价值,就像上面所说的那样,而且可能会引起混淆,“不完整”代码该如何处理(用户是有意留下它,还是刚要输入下一个参数?)。
您正确地指出params落入了“概念性”差距,因为您将其视为数组,并且可以指定它们为逗号分隔(在集合初始化程序之前支持)。那么为什么它们的风格与集合初始化程序不同呢?

params 的语言规范并没有明确指定支持尾随逗号,尽管对于集合初始化程序来说是这样的,以达到与其他语言(我想是C ++)的一致性,这增加了从其他语言迁移到 C#的开发人员的熟悉感。

我的推测是:由于它不在规范中,因此导致 YAGNI 应用,从那时起,该功能的价值主张毫无疑问地倾向于不实现。


2
用户是故意留在那里还是即将输入下一个参数?这种推理同样适用于枚举和初始化列表。此外,生成的代码中也存在方法调用,并且也正在合并 :) - BartoszKP
2
确实如此,但是推理并不重要,因为编译器并不试图连接未知的枚举值。我认为它属于最小价值和开发成本的范畴。肯定有支持这种做法的论点,我也不会反驳任何一方的观点。我只是试图推测事情为什么会变成现在这个样子。 - Adam Houldsworth
1
你评论中提到的“未知值”部分似乎正中要害。你回答中的概念差距也很明显——它们似乎是最相关的,其他部分几乎是噪音;)虽然总体上这是对这个难题的不错尝试。 - BartoszKP
1
@BartoszKP 谢谢 :-) 我同意你的观点。它似乎可以得到支持,并且属于枚举等参数类别的相同论点。谁知道,现在Roslyn正在实现更快的迭代和更低的开发成本,我们可能会看到这些有争议的不一致性开始得到解决。 - Adam Houldsworth

3

如果您查看词法语法,请点击此处

C.2.9 数组

array-initializer:
{   variable-initializer-listopt   }

{   variable-initializer-list   ,   }// This comma is causing this

variable-initializer-list:
variable-initializer
variable-initializer-list   ,   variable-initializer

调用函数的方法是这样的....MethodName(形式参数列表可选);
 formal-parameter-list:
 fixed-parameters
fixed-parameters   ,   parameter-array
parameter-array
fixed-parameters:
fixed-parameter
fixed-parameters   ,   fixed-parameter
fixed-parameter:
attributesopt   parameter-modifieropt   type   identifier
parameter-modifier:
ref
out
parameter-array:
attributesopt   params   array-type   identifier

由于语言的书写方式,不允许使用尾随逗号,具体原因我不清楚,但 Adam 可以解释。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接