Allow named arguments to be used in non-trailing position, as long as they are used in their correct position. For example: `DoSomething(isEmployed:true, name, age);`.
## Motivation
[motivation]: #motivation
The main motivation is to avoid typing redundant information. It is common to name an argument that is a literal (such as `null`, `true`) for the purpose of clarifying the code, rather than of passing arguments out-of-order.
That is currently disallowed (`CS1738`) unless all the following arguments are also named.
```C#
DoSomething(isEmployed:true, name, age); // currently disallowed, even though all arguments are in position
// CS1738 "Named argument specifications must appear after all fixed arguments have been specified"
```
Some additional examples:
```C#
public void DoSomething(bool isEmployed, string personName, int personAge) { ... }
DoSomething(isEmployed:true, name, age); // currently CS1738, but would become legal
DoSomething(true, personName:name, age); // currently CS1738, but would become legal
In §7.5.1 (Argument lists), the spec currently says:
> An *argument* with an *argument-name* is referred to as a __named argument__, whereas an *argument* without an *argument-name* is a __positional argument__. It is an error for a positional argument to appear after a named argument in an *argument-list*.
In particular, this prevents invoking `void M(bool a = true, bool b = true, bool c = true, );` with `M(c: false, valueB);`. The first argument is used out-of-position (the argument is used in first position, but the parameter named "c" is in third position), so the following arguments should be named.
This proposal exacerbates existing subtleties with named arguments in overload resolution. For instance:
```
void M(int x, int y) { }
void M<T>(T y, int x) { }
void M2()
{
M(3, 4);
M(y: 3, x: 4); // Invokes M(int, int)
M(y: 3, 4); // Invokes M<T>(T, int)
}
```
You could get this situation today by swapping the parameters:
```
void M(int y, int x) { }
void M<T>(int x, T y) { }
void M2()
{
M(3, 4);
M(x: 3, y: 4); // Invokes M(int, int)
M(3, y: 4); // Invokes M<T>(int, T)
}
```
Similarly, if you have two methods `void M(int a, int b)` and `void M(int x, string y)`, the mistaken invocation `M(x: 1, 2)` will produce a diagnostic based on the second overload ("cannot convert from 'int' to 'string'"). This problem already exists when the named argument is used in a trailing position.
- Providing IDE assistance to fill-in all the names of trailing arguments when you type specific a name in the middle.
Both of those suffer from more verbosity, as they introduce multiple named arguments even if you just need one name of a literal at the beginning of the argument list.
The feature was briefly discussed in LDM on May 16th 2017, with approval in principle (ok to move to proposal/prototype). It was also briefly discussed on June 28th 2017.