Short Version: A named argument following an out
argument gives a compiler error, but I cannot find any support for this behaviour in the language specification.
Long Version:
I'm using the Enum.TryParse<TEnum>
three parameter overload, but I would prefer to name the ignoreCase
parameter to make my code clearer, a call like:
MyEnum res;
b = Enum.TryParse<MyEnum>(inputString, true, out res);
leaves the meaning of the boolean unclear (unless this method is known1). Hence I would like to use:
b = Enum.TryParse<MyEnum>(inputString, out res, ignoreCase: true);
However the compiler reports this as an error:
Named argument 'ignoreCase' specifies a parameter for which a positional argument has already been given
and the IDE highlights the ignoreCase
parameter. VS2010 targeting .NET 4, and VS11 Beta targeting either 4 or 4.5 all give the same result. In all cases naming the out
parameter removes the error.
b = Enum.TryParse<MyEnum>(inputString, result: out res, ignoreCase: true);
I've tried this across a number of different methods (including avoiding generics)2, both from the framework and in my assembly: always the same result: an out
parameter followed by a named parameter gives an error.
I can see no reason for this error, and §7.5.1 Argument Lists of the C# Language Specification: Version 4.0 does not seem to provide any reason why an out
followed by a named parameter should give an error. The text of the error seems to support an interpretation as a bug: there is no positional argument which could be a valid match for ignoreCase
.
Is my reading of the specification wrong? Or is this a compiler bug?
C# 7.2 Update
This restriction on all named arguments have to follow positional arguments when calling was lifted with C# 7.2.
See https://learn.microsoft.com/en-gb/dotnet/csharp/whats-new/csharp-7-2#non-trailing-named-arguments.
1 Hence the advice in the Framework Design Guidelines to prefer enum
parameters.
2 Eg: given:
private static void TestMethod(int one, float two, out string three) {
three = "3333";
}
this this call also gives the same error on the named parameter unless the out
parameter is also named:
TestMethod(1, out aString, two: 1.0f);
Named parameters do not allow you to "skip" positional arguments.
Your code is parsed as passing the first two arguments—value
and ignoreCase
, then passing ignoreCase
again.
It has nothing to do with the out
ness of the parameter.
You can fix it by passing the last parameter as named too.