我在 MS 文档中发现了这种语法:
public NewsStoryViewModel(DateTimeOffset published, string title, string uri) =>
(Published, Title, Uri) = (published, title, uri);
Run Code Online (Sandbox Code Playgroud)
它在一个语句中进行多项赋值,但我不太确定它叫什么或它是如何工作的。
这是通过假装这些是元组来进行多重赋值的某种技巧还是它有自己的名字?
PS如果有人感兴趣,这里会提到
PPS 我想知道的不是 {} 的缺失,而是第 2 行的“花哨”分配而不是传统分配。
它是一个被解构为类属性的元组。
public NewsStoryViewModel(DateTimeOffset published, string title, string uri) {
// tuple
var myTuple = (published, title, uri);
// deconstruction
(Published, Title, Uri) = myTuple;
}
Run Code Online (Sandbox Code Playgroud)
解构适用于开箱即用的元组。有关详细信息,请参阅https://docs.microsoft.com/en-us/dotnet/csharp/tuples#deconstruction。
我不知道他们是否有专门在构造函数中执行此操作的官方术语,它被称为解构作为一般模式。只要赋值的右边有合适的Deconstruct方法,你就可以从一个类型中提取值,像这样批量执行赋值。对于元组,这个:
var (x, y, z) = (1, 2, 3);
Run Code Online (Sandbox Code Playgroud)
在道德上等同于
var tuple = (1, 2, 3);
var x = tuple.Item1;
var y = tuple.Item2;
var z = tuple.Item3;
Run Code Online (Sandbox Code Playgroud)
左侧可以有任何可分配的变量,它们可以是构造函数中的局部变量、字段或仅获取属性。使用它是个人喜好和代码风格,我通常像在 MSDN 文档中一样使用它们 - 在一行中编写基本的构造函数:
class C
{
private int Prop1 { get; }
private D Prop2 { get; }
private string Prop3 { get; }
public C(int prop1, D prop2, string prop3) =>
(Prop1, Prop2, Prop3) = (prop1, prop2, prop3);
}
Run Code Online (Sandbox Code Playgroud)
一个有趣的事实是 Roslyn 编译器识别这种模式并避免实际创建元组。如果将其放入反编译器,您将看到生成的代码与 for 相同:
var (x, y, z) = (1, 2, 3);
Run Code Online (Sandbox Code Playgroud)
我不知道它是否在任何地方都有记录,但要归功于 Jon Skeet,他在他的 C# in Depth(第 4 版)中提到了这一点。
更新:出于好奇,我检查了优化是否也适用于其他地方。只要左侧的变量是ref或out参数,它似乎就可以工作。例如这个:
var tuple = (1, 2, 3);
var x = tuple.Item1;
var y = tuple.Item2;
var z = tuple.Item3;
Run Code Online (Sandbox Code Playgroud)
生成与此等效的代码:
class C
{
private int Prop1 { get; }
private D Prop2 { get; }
private string Prop3 { get; }
public C(int prop1, D prop2, string prop3) =>
(Prop1, Prop2, Prop3) = (prop1, prop2, prop3);
}
Run Code Online (Sandbox Code Playgroud)
我有根据的猜测是,由于 IL 在对“正常”变量和ref变量的分配之间有所不同,因此对于第二种情况根本没有实现优化,但我可能是错的。