C# 7.0值元组的编译错误?

40

当我尝试编译以下代码时:

var post = iPostService.GetAll().Select(x => (x.Title, x.Author));

我得到了编译器错误:'表达式树可能不包含元组字面值。'

所以我也尝试了这个:

var post = iPostService.GetAll().
                    Select(x => new ValueTuple<string, string>(x.Title, x.Author))
运行时错误:'无法解析方法Void.ctor(System.String, System.String),因为方法句柄的声明类型System.ValueTuple`2[T1,T2]是泛型的。 显式地提供声明类型以从GetMethodFromHandle获取方法。' 我谷歌搜索了解决此问题的方法,但没有找到真正有帮助的内容。 非常感谢任何帮助。 谢谢。

1
原始问题由元组表达式树支持。#12897跟踪。但是看起来你无法在编译时表达式中以任何方式使用ValueTuple,所以恐怕目前没有解决方案/解决方法。 - Ivan Stoev
这现在可以用 EF Core 实现了。 - quitprog
2个回答

34

对我来说有效,首先创建一个元组然后转换为ValueTuple:

var post = iPostService.GetAll().
           Select(x => new Tuple<string, string>(x.Title, x.Author).ToValueTuple())

2
太棒了!这个问题一直阻止我模拟我的automapper方法CreateMap(我在其中使用了一个元组)。关于为什么存在这个问题(“表达式树可能不包含元组文字”)的更多信息,请参见此处:https://www.damirscorner.com/blog/posts/20181207-NoSupportForTuplesInExpressionTrees.html - Luis Gouveia

17

最后,我发现我的代码问题所在:

  • 我使用了延迟执行,因此数据在构造函数执行时不会从数据库加载。
  • 解决方法是在创建实例命令之前添加转换运算符。

希望它对你的代码有用。


6
针对延迟执行的问题,在我的情况下,我只是在Select()语句之前添加了.AsEnumerable()。 - Jack
4
正如@jack所说。在Select()投影之前添加AsEnumerable()将使lambda变为委托函数,而不是表达式树,这确实允许元组字面量。 - PillowMetal
1
没错,我可以确认,我没有意识到我的 Select 在 EF-materializing AsEnumerable、ToArray 等之前,所以似乎元组不能用于生成表达式树来生成 SQL,就像空合并运算符一样。简单的解决办法是先进行材料化。 - nh43de

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接