[英]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.