问题 为什么C#允许在集合初始值设定项中使用尾随逗号而不在params中?


有效语法:

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

无效的语法:

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

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

这是语法不一致还是计算决策的问题?


3554
2017-11-11 12:32


起源

在第二个示例中,编译器使用逗号分隔方法参数,而不是集合项。 params 是单独处理。在方法参数上,您从未能够留下尾随逗号。 - Adam Houldsworth
编译器不是人类,它不知道并且不关心您是否要将集合传递给方法。它只是“看到”语法无效。前一种语法是有效的,因为语言规范允许初始化集合。 - Tim Schmelter
此问题被错误地关闭为重复。 相关问题 回答“我们为什么允许在收集初始化程序上使用逗号”,而这是在问“为什么我们不允许使用逗号尾随逗号” params 方法参数“。那就是说,答案是相似的 - 但问题不是。 - Adam Houldsworth
区别在于方法调用看起来是否相同 params。技术上可能是可能的,但是 params 和初始化器后来添加。 - BartoszKP
这就是为什么在第一种情况下允许使用逗号的原因: stackoverflow.com/questions/2147333/...  我认为不同之处在于,在初始化列表时,您列出了相同类型的元素,但在调用函数时,您可以在其中进行任何操作,因此语法要严格得多。 - Andrew


答案:


所以我会对此进行一次尝试,即使我永远不会知道“真正”的原因,因为我不在编译器团队中 - 而且一个人出现的可能性值得怀疑。

尾随逗号在一些场景中通常很有用,即合并和代码生成。在收集或属性初始化器和枚举之类的上下文中,留下尾随逗号是无害的(编译器可以安全地推断出“列表的结尾”,因为它还可以挂钩到它的闭合块括号。

方法参数非常明确 - 编译器需要在此区域进行大量控制,以便在人们编码和其他辅助功能时提供良好的反馈。在方法参数上留下一个尾随逗号不会添加上面的任何值,并且我开始对如何处理“不完整”代码造成混淆(用户是故意将它留在那里还是他们只是要在下一个参数中输入?)。

你是对的 params 落入 概念上的 您将它们视为数组的间隙,您可以将它们指定为逗号分隔(在集合初始化之前支持)。那么为什么它们会从收藏初始化者的风格中脱离出来?

语言规范 params bit没有明确指定尾随逗号支持,虽然它适用于集合初始化程序以实现与其他语言(我认为是C ++)的奇偶校验,这增加了开发人员从其他地方迁移到C#的熟悉程度。

我的假设:事实上它不符合规范然后导致 YAGNI 申请,从那时起,该功能的价值主张是一个明智的选择,而不是实现它。


10
2017-11-11 12:57



“用户是故意将它留在那里还是他们只是打算输入下一个论点?”推理同样适用于枚举和初始化列表。此外,方法调用也存在于生成的代码中,并且也正在合并:) - BartoszKP
实际上,但推理并不重要,因为编译器并没有尝试连接未知的枚举值。我认为它属于最低价值和发展成本的范畴。肯定存在争论,我不论是哪种方式都是争论。我只是想弄清楚为什么事情就像他们一样。 - Adam Houldsworth
你评论中关于“未知价值”的部分似乎在这一点上出现了。你的答案中的概念差距也是 - 它们似乎是最相关的,其他部分几乎是噪音;)虽然总体上很好地尝试了这个难题。 - BartoszKP
@BartoszKP谢谢:-)我同意你的观点。似乎它可以得到支持,并且与enums等人一样属于相同的论点类别。谁知道,既然Roslyn正在实现更快的迭代和更低的开发成本,我们可能会看到这些争议不一致的问题开始得到解决。 - Adam Houldsworth


如果你看看词汇语法 这里 

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

 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

没有留下逗号的地方 这是因为语言是这样写的,我不知道原因,但亚当知道


1
2017-11-11 13:15