c# - 如何将 ValueTuple 命名功能与匿名方法一起使用?

标签 c# ienumerable anonymous-methods valuetuple

我想按如下方式使用 ValueTuple 的命名功能:

     IEnumerable<(string, char, int)> valueTuples = new(string, char, int)[]
     {
        ("First", '1', 1),
        ("Second", '2', 2),
        ("Third", '3', 3)
     };

     var projection1 = valueTuples.Select(((string s, char c, int i) tuple) => tuple.i);

但它不会编译并显示一条不是很有帮助的错误消息。然而,这些都编译:

     var projection2 = valueTuples.Select(tuple => tuple.Item1);

     var projection3 = valueTuples.Select(((string, char, int) tuple) => tuple.Item1);

尝试更直接的方法,这不会编译但会出错 更有帮助的消息:

     var projection4 = Enumerable.Select(
        valueTuples, ((string s, char c, int i) tuple) => tuple.i);

这导致尝试这个,编译:

     var projection5 = Enumerable.Select<(string, char, int), int>(
        valueTuples, ((string s, char c, int i) tuple) => tuple.i);

这最终激发了这个,它编译:

     var projection6 = valueTuples.Select<(string, char, int), int>(
        ((string s, char c, int i) tuple) => tuple.i);

这是 IEnumerable 扩展方法的普遍问题吗? 看起来不是因为这个编译:

     var filtered = valueTuples.Where(((string s, char c, int i) tuple) => tuple.i > 1);

为什么我必须求助于 projection6 语法才能让它工作?

最佳答案

你有一个未命名的元组列表 (string, char, int)(注意没有名字)。因此,使用默认名称 Item1Item2 等访问可以正常工作。

但是,您传递给 Select 的 lamdba 被命名为元组类型:

(string s, char c, int i) tuple) => tuple.i

似乎类型推断没有考虑命名和未命名元组(或两个具有不同名称的命名元组)完全相同,并且在某些情况下使用这种“不同”类型时推断失败。我不完全确定为什么,它甚至可能是一个错误,或者规范中可能包含某些内容。

但是,有了这些知识,我们可以找出解决问题的最佳方法是从一开始就使用命名元组类型:

IEnumerable<(string s, char c, int i)> valueTuples = new[] {
    ("First", '1', 1),
    ("Second", '2', 2),
    ("Third", '3', 3)
};            
var projection1 = valueTuples.Select(tuple => tuple.i);

更新:我实际上找到了一个 issue关于这个在 Roslyn 存储库中。这确实是一个已确认的错误,甚至已经解决了。没有关于此错误性质的解释。修复应该出现在版本 15.7 中。

即使有修复,我仍然认为从一开始就使用命名元组是最好的方法。然后你就不需要在每个 lambda 中一次又一次地指定名称(这些名称甚至可以不同,这使得整个事情更加困惑)。

关于c# - 如何将 ValueTuple 命名功能与匿名方法一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50072761/

相关文章:

c# - 可以将 Excel 文档加载到内存中、填充并以字节形式返回吗?

c# - 原生 C++ 还是 .NET for Business App?

c# - 如何将类型传递给方法?

c# - ASP.NET 核心 (MVC) : Can't get to the Login HttpPost action in controller

c# - 我应该使用什么作为方法 IEnumerable、IList、Collection 或什么的返回类型

Delphi:强制捕获匿名方法的 "unused"变量

c# - 我怎样才能减少 IEnumerable<IEnumerable<Foo>> 到 IEnumerable<Foo>?

c# - 为什么这段使用 yield return 的代码可以编译?

C# 抽象类,使用匿名而不是声明具体类?

c# - 如何通过 lambda 表达式传递捕获的变量,就好像它未被捕获一样?