C# 7 元组和 lambda

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 中实际解包一个元组(也许为什么它没有实现或不可能)。如果您是来这里寻找默认名称的解决方案,请阅读

编辑 2:

只是想到了一个更一般的用例:是否可以(或为什么不可以)将 "deconstruct" 元组传递给方法?像这样:

void Foo((int,int)(x,y)) { x+y; }

而不是这个:

void Foo((int x,int y) value) { value.x+value.y }

您应该指定元组属性的名称(嗯,ValueTuple 有字段)否则将使用默认名称,如您所见:

var list = new List<(int x, int y)>();

现在元组有很好命名的字段供您使用

list.Select(t => t.x * 2 + t.y / 2)

不要忘记从 NuGet 添加 System.ValueTuple 包,并记住 ValueTuples 是可变结构。


更新:解构目前仅表示为对现有变量的赋值(解构赋值)或对新创建的局部变量(解构声明)的赋值。适用函数成员选择算法同前:

Each argument in argument list corresponds to a parameter in the function member declaration as described in §7.5.1.1, and any parameter to which no argument corresponds is an optional parameter.

元组变量是单个参数。不能对应方法形参列表中的多个参数

您 运行 遇到的问题是编译器无法推断此表达式中的类型:

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

它会起作用。

如您所见,对于:

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

这些目前都不可能。但是,问题 Proposal: Tuple deconstruction in lambda argument list 存在于 GitHub 的 dotnet/csharplang 存储库中,要求语言团队在未来的 C# 版本中考虑这些功能。如果您也希望看到对此的支持,请将您的声音添加到该主题中。

C# 7.0 中的解构支持三种形式:

  • 解构声明(如(var x, var y) = e;),
  • 解构赋值(如(x, y) = e;),
  • 和解构-foreach(如foreach(var(x, y) in e) ...)。

考虑了其他上下文,但实用性可能会降低,我们无法在 C# 7.0 时间范围内完成它们。 let 子句 (let (x, y) = e ...) 和 lambda 中的解构似乎是未来扩展的好候选。

后者正在 https://github.com/dotnet/csharplang/issues/258

中讨论

请在那里表达您的反馈和兴趣,因为这将有助于支持提案。

有关 design doc 中 C# 7.0 解构中包含的内容的更多详细信息。