[英]C# 7 tuples and lambdas
使用新的 c# 7 元组语法,是否可以指定一个带有元组作为参数的 lambda 并在 lambda 中使用解压值?
例子:
var list = new List<(int,int)>();
在 lambda 中使用元组的正常方法:
list.Select(value => value.Item1*2 + value.Item2/2);
我希望一些新的糖可以避免.Item1
.Item2
,例如:
list.Select((x,y) => x*2 + y/2);
最后一行不起作用,因为它被视为 lambda 的两个参数。 我不确定是否有办法真正做到这一点。
编辑:
我在 lambda 定义中尝试了双括号,但没有奏效: ((x,y)) => ...
,也许尝试起来很愚蠢,但双括号实际上在这里起作用:
list.Add((1,2));
另外,我的问题并不是关于避免丑陋的默认名称.Item .Item2
,而是关于在 lambda 中实际解包一个元组(也许为什么它没有实现或不可能实现)。 如果您来这里是为了解决默认名称,请阅读Sergey Berezovskiy 的回答。
编辑2:
只是想到了一个更一般的用例:是否有可能(或为什么不)“解构”传递给方法的元组? 像这样:
void Foo((int,int)(x,y)) { x+y; }
取而代之的是:
void Foo((int x,int y) value) { value.x+value.y }
正如您所观察到的,对于:
var list = new List<(int,int)>();
人们至少希望能够做到以下几点:
list.Select((x,y) => x*2 + y/2);
但是 C# 7 编译器(还)不支持这一点。 需要糖以允许以下内容也是合理的:
void Foo(int x, int y) => ...
Foo(list[0]);
与编译器转换Foo(list[0]);
到Foo(list[0].Item1, list[0].Item2);
自动地。
目前这两种方法都不可能。 但是,GitHub 上的dotnet/csharplang
库中存在问题Proposal: Tuple deconstruction in lambda argument list ,要求语言团队在 C# 的未来版本中考虑这些功能。 如果您也希望看到对此的支持,请务必将您的声音添加到该线程中。
您应该指定元组属性的名称(好吧,ValueTuple 有字段),否则将使用默认名称,如您所见:
var list = new List<(int x, int y)>();
现在元组有很好命名的字段,您可以使用
list.Select(t => t.x * 2 + t.y / 2)
不要忘记从 NuGet 添加System.ValueTuple包,并记住 ValueTuples 是可变结构。
更新:解构当前仅表示为对现有变量(解构赋值)或新创建的局部变量(解构声明)的赋值。 适用的函数成员选择算法与之前相同:
参数列表中的每个参数对应于第 7.5.1.1 节中描述的函数成员声明中的一个参数,任何没有参数对应的参数都是可选参数。
元组变量是单个参数。 它不能对应方法的形参列表中的几个参数。
C# 7.0 中的解构支持三种形式:
(var x, var y) = e;
),(x, y) = e;
),foreach(var(x, y) in e) ...
)。 考虑了其他上下文,但实用性可能会下降,我们无法在 C# 7.0 时间范围内完成它们。 let 子句( let (x, y) = e ...
)和 lambdas 中的解构似乎是未来扩展的好候选者。
后者正在https://github.com/dotnet/csharplang/issues/258中讨论
请在那里表达您的反馈和兴趣,因为这将有助于支持提案。
有关设计文档中 C# 7.0 解构中包含的内容的更多详细信息。
您遇到的问题是编译器无法推断此表达式中的类型:
list.Select(((int x, int y) t) => t.x * 2 + t.y / 2);
但由于(int, int)
和(int x, int y)
是相同的 CLR 类型( System.ValueType<int, int>
),如果您指定类型参数:
list.Select<(int x, int y), int>(t => t.x * 2 + t.y / 2);
它会起作用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.