我不知道他们是否有针对构造函数特别称呼这种操作的官方术语,但作为一般模式,它被称为解构。只要赋值的右侧具有适当的Deconstruct
方法,您就可以像这样批量提取类型中的值并执行赋值操作。对于元组,可以这样做:
var (x, y, z) = (1, 2, 3);
在道德上等同于
var tuple = (1, 2, 3);
var x = tuple.Item1;
var y = tuple.Item2;
var z = tuple.Item3;
左侧可以有任何可分配变量,它们可以是构造函数中的本地变量、字段或只读属性。使用它是个人偏好和代码风格,我通常按照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);
}
有趣的是,Roslyn编译器能够识别这种模式并避免实际创建元组。如果你将其输入反编译器,你会发现生成的代码与以下代码相同:
public C(int prop1, D prop2, string prop3)
{
Prop1 = prop1;
Prop2 = prop2;
Prop3 = prop3;
}
我不知道这是否有记录,但要感谢Jon Skeet在他的《C#深度剖析》(第4版)中提到了这一点。
更新:
出于好奇,我检查了一下是否还可以在其他地方应用此优化。似乎只要左侧变量是
ref
或
out
参数就可以。例如:
public void Deconstruct(out int prop1, out object prop2, out string prop3) =>
(prop1, prop2, prop3) = (_prop1, _prop2, _prop3);
生成等效于此代码的代码:
public void Deconstruct(out int prop1, out object prop2, out string prop3)
{
int temp1 = _prop1;
object temp2 = _prop2;
string temp3 = _prop3;
prop1 = temp1;
prop2 = temp2;
prop3 = temp3;
}
我猜测,由于对“普通”变量和ref
变量进行赋值时中间语言不同,因此第二种情况的优化可能没有实现,但我可能是错误的。