带有可选参数的params的显式数组?

时间:2013-12-10 15:24:30

标签: c#

void Main()
{
    //Thing(x:1, s:string.Empty, hello:new Hello(), new Hello());
    Thing(x:1, s:string.Empty, hello:new[]{ new Hello(), new Hello()});
}

public void Thing(int x, string s = "", params Hello[] hello)
{
}

public class Hello { }

为什么我需要指定一个数组,以便在与可选参数一起使用时使params有效?或者我是吗?使用标签的唯一原因是因为我最初想要排除可选参数

3 个答案:

答案 0 :(得分:1)

你可以做,

Thing(1, string.Empty, new Hello(), new Hello());

因为您使用的是params

就此而言,所有这些都是兼容的。

Thing(1);
Thing(2, string.Empty);
Thing(3, string.Empty, null);
Thing(4, string.Empty, new Hello());
Thing(-69, "negative feeback", new Hello(), null);
Thing(42, "the meaning of life", new Hello(), new Hello());
Thing(666, theBeast.ToString(), new Hello(), new Hello(), new Hello());
// etc. etc.

从你的评论我认为你的问题实际上是,

  

为什么在使用参数名称时必须构造params数组?

这个问题是duplicate,但总的来说,这是因为它的工作方式。


如果您想省略s并获得params的好处,为什么不宣布过载,

public void Thing(int x, string s = "", params Hello[] hellos)
{
}

public void Thing(int x, params Hello[] hellos)
{
    this.Thing(x, string.Empty, hellos);
}

然后您仍然可以按预期使用params,并且不需要使用参数名称。

此功能比可选参数更早,并且在很大程度上减轻了您的需求,我想这就是为什么它从未得到解决。

答案 1 :(得分:1)

因为这就是params的工作方式 - 从技术上讲,它是一个数组参数,编译器将根据您的参数列表生成。当前的C#规范不支持将多个值传递到一个命名参数而不捆绑它们。如果要将参数名称用于质量多个值,则必须将参数捆绑在一个数组中。

这些应该有效:

Thing(x:1, hello:new[]{ new Hello(), new Hello()}); // 2 values
Thing(x:1, hello:new Hello());  // one value
Thing(x:1); // no values

如果您认为这是编译器相对于实现它所需的 cost 有价值的,那么请随时在Microsoft Connect上发布建议

答案 2 :(得分:1)

嗯,命名参数和params有相互冲突的规则:命名参数可以按任何顺序出现,params必须在最后。根据前者,我们应该能够做到这一点:

Thing(1, hello:new Hello(), new Hello(), s:string.Empty);

编译器当然可以解释如何解释它,但读者不像通常那样在末尾使用params。但如果hello:被强制放在最后,这将与命名参数不一致,并删除你原本会有的一些灵活性。

简而言之,我认为要求一个显式数组是一种妥协,可以保持最大的一致性。