Why can't an expression tree contain a named argument specification?

c#, c#-4.0, expression-trees

Solution

Consider the following:

static int M() { Console.Write("M"); return 1; }
static int N() { Console.Write("N"); return 2; }
static int Q(int m, int n) { return m + n; }
...
Func<int> f = ()=>Q(n : N(), m: M());
Expression<Func<int>> x = ()=>Q(n : N(), m: M());
Func<int> fx = x.Compile();
Console.WriteLine(f());
Console.WriteLine(fx());

You agree I hope that the last two lines must do exactly the same thing, right? Which is to print `NM3`.

Now, what expression tree library calls would you like the expression tree conversion to generate that ensure this? There are none! We are therefore faced with the following choices:

- Implement the feature in the expression tree library. Add a transformation in the expression tree lowering engine that preserves the order of execution of the named arguments. Implement code in the `Compile` method that takes the execution order into account.

- Make `x = ()=>Q(n : N(), m: M());` actually be implemented as `x = ()=>Q(M(), N());` and be incompatible with the non-expression-tree version.

- Disallow named arguments in expression trees. Implement an error message to that effect.

(1) is nice, but expensive. (2) is a non-starter; we can't in good conscience introduce this kind of "gotcha". (3) is cheap but irritating.

We chose (3).

Problem

Using AutoMapper, I hit a place where a named argument would've fit very nicely: ``` .ForMember(s => s.MyProperty, opt => opt.MapFrom(s => BuildMyProperty(s, isAdvanced: false))) ``` But the compiler yelled at me: An expression tree may not contain a named argument specification So I had to revert to: ``` .ForMember(s => s.MyProperty, opt => opt.MapFrom(s => BuildMyProperty(s, false))) ``` Does anyone know why the compiler disallows named arguments in this situation?

Original source