编程语言
首页 > 编程语言> > c# – 如何将ValueTuple命名功能与匿名方法一起使用?

c# – 如何将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);

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

     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语法才能使其工作?

解决方法:

你有一个未命名的元组列表(字符串,字符,整数)(注意没有名称).因此,使用默认名称Item1,Item2等进行访问可以正常工作.

但是,传递给Select lamdba的是名为tuple类型:

(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);

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

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

标签:c,anonymous-methods,ienumerable,valuetuple
来源: https://codeday.me/bug/20190607/1194741.html