为什么表达式树不能包含命名参数规范?

Bra*_*ton 40 c# expression-trees c#-4.0

使用AutoMapper,我找到了一个命名参数非常适合的地方:

.ForMember(s => s.MyProperty, opt => opt.MapFrom(s => BuildMyProperty(s, isAdvanced: false)))
Run Code Online (Sandbox Code Playgroud)

但编译器对我大吼:

表达式树可能不包含命名参数规范

所以我不得不回复:

.ForMember(s => s.MyProperty, opt => opt.MapFrom(s => BuildMyProperty(s, false)))
Run Code Online (Sandbox Code Playgroud)

有谁知道为什么编译器在这种情况下不允许使用命名参数?

Eri*_*ert 31

考虑以下:

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());
Run Code Online (Sandbox Code Playgroud)

你同意我希望最后两行必须做同样的事情,对吗?哪个是打印的NM3.

现在,您希望表达式树转换生成哪个表达式树库,以确保这一点?没有了!因此,我们面临以下选择:

  1. 在表达式树库中实现该功能.在表达式树降低引擎中添加转换,以保留命名参数的执行顺序.在将Compile执行顺序考虑在内的方法中实现代码.
  2. Make x = ()=>Q(n : N(), m: M());实际上x = ()=>Q(M(), N());与非表达式树版本一起实现并且不兼容.
  3. 禁止在表达式树中使用命名参数.实现该效果的错误消息.

(1)很好,但很贵.(2)是非首发; 我们不能凭良心介绍这种"陷阱".(3)便宜但刺激性.

我们选择了(3).

  • @DrPhil:如果十年前我写这个答案时已有记录,我可能会想到这个选项。 (4认同)
  • @BrandonLinton:开发、测试、记录和维护成本很高,特别是与它提供的非常小的好处相比。我们本来可以选择在一开始就支持它——毕竟,VB 一直为方法调用命名参数——但我们选择不这样做。 (2认同)
  • 不是有选项 4:“允许在表达式树中使用命名参数,只要它们的顺序相同”?对于“记录”,按与构造函数定义相同的顺序对主构造函数使用命名参数是很常见的。 (2认同)