6

简短版本:参数后面的命名参数out会产生编译器错误,但我在语言规范中找不到对这种行为的任何支持。

长版

我正在使用Enum.TryParse<TEnum>三参数重载,但我更愿意命名ignoreCase参数以使我的代码更清晰,这样的调用:

MyEnum res;
b = Enum.TryParse<MyEnum>(inputString, true, out res);

使布尔值的含义不清楚(除非此方法已知1)。因此我想使用:

b = Enum.TryParse<MyEnum>(inputString, out res, ignoreCase: true);

但是编译器将此报告为错误:

命名参数 'ignoreCase' 指定一个已经给出位置参数的参数

IDE 会突出显示该ignoreCase参数。针对 .NET 4 的 VS2010 和针对 4 或 4.5 的 VS11 Beta 都给出了相同的结果。在所有情况下,命名out参数都会消除错误。

b = Enum.TryParse<MyEnum>(inputString, result: out res, ignoreCase: true);

我已经在框架和我的程序集中尝试了许多不同的方法(包括避免泛型)2:总是相同的结果:一个out参数后跟一个命名参数会产生错误。

我看不出这个错误的原因,并且C# 语言规范的§7.5.1参数列表:版本 4.0似乎没有提供任何原因说明out后面的命名参数应该给出错误。错误的文本似乎支持将其解释为错误:没有位置参数可以有效匹配ignoreCase.

我对规范的阅读是错误的吗?或者这是一个编译器错误?

C# 7.2 更新

当使用 C# 7.2 取消调用时,对所有命名参数的限制必须遵循位置参数。

请参阅https://docs.microsoft.com/en-gb/dotnet/csharp/whats-new/csharp-7-2#non-trailing-named-arguments


1因此,框架设计指南中的建议是首选enum参数。

2例如:给定:

private static void TestMethod(int one, float two, out string three) {
  three = "3333";
}

out除非参数也被命名,否则此调用也会在命名参数上给出相同的错误:

TestMethod(1, out aString, two: 1.0f);
4

2 回答 2

8

命名参数不允许您“跳过”位置参数。

您的代码被解析为传递前两个参数value- 和ignoreCase,然后ignoreCase再次传递。
与参数的好坏无关out

您也可以通过传递命名的最后一个参数来修复它。

于 2012-03-13T16:27:34.767 回答
4

每个位置参数都需要匹配,如果您通过命名参数开始重新排列顺序,则必须重新排列您命名的参数之后的所有参数。

所以这行代码:

b = Enum.TryParse<MyEnum>(inputString, out res, ignoreCase: true);

尝试与 匹配out resignoreCase然后您再次命名该参数,这会使编译器跳闸。可能还有另一个错误隐藏在第一个错误后面,out resignoreCase.

所以如果你想在处理位置参数时“跳过”ignoreCase,你也必须命名out res参数。

于 2012-03-13T16:29:06.333 回答