析构表达式 - 从元组或其他用户定义的类型中提取字段的属性
析构表达式从对象的实例中提取数据字段。 每个离散数据元素将写入不同的变量,如以下示例所示:
var tuple = (X: 1, Y: 2);
var (x, y) = tuple;
Console.WriteLine(x); // output: 1
Console.WriteLine(y); // output: 2
前面的代码片段创建了一个元组,它有两个整数值 X
和 Y
。 第二个语句 将 解构元组,并将元组元素存储在离散变量 x
和 y
中。
元组析构
所有元组类型都支持析构表达式。 元组析构提取所有元组的元素。 如果只想使用某些元组元素,请对未使用的元组成员使用弃元,如以下示例所示:
var tuple2 = (X: 0, Y: 1, Label: "The origin");
var (x2, _, _) = tuple2;
在前面的示例中,将丢弃 Y
和 label
成员。 可以在同一解构表达式中指定多个弃元。 可以对元组的所有成员使用丢弃。 以下示例是合法的,但没有用:
var (_, _, _) = tuple2;
记录析构
具有主构造函数的记录类型支持对位置参数的析构。 编译器合成 Deconstruct
方法,该方法提取从主构造函数中的位置参数合成的属性。 编译器合成的 Deconstruction
方法不会提取在记录类型中声明为属性的属性。
以下代码中显示的 record
声明两个位置属性SquareFeet
和 Address
,以及另一个属性 RealtorNotes
:
public record House(int SquareFeet, string Address)
{
public required string RealtorNotes { get; set; }
}
析构 House
对象时,所有的位置属性(并且只有位置属性)被析构,如以下示例所示:
var house = new House(1000, "123 Coder St.")
{
RealtorNotes = """
This is a great starter home, with a separate room that's a great home office setup.
"""
};
var (squareFeet, address) = house;
Console.WriteLine(squareFeet); // output: 1000
Console.WriteLine(address); // output: 123 Coder St.
Console.WriteLine(house.RealtorNotes);
可以使用此行为来指定记录类型的哪些属性是编译器合成 Deconstruct
方法的一部分。
声明 Deconstruct
方法
可以向所声明的任何类、结构或接口添加析构支持。 可以在类型中声明一个或多个 Deconstruct
方法,或声明为该类型的扩展方法。 析构表达式调用方法 void Deconstruct(out var p1, ..., out var pn)
。 Deconstruct
方法可以是实例方法或扩展方法。 Deconstruct
方法中每个参数的类型必须与析构表达式中相应参数的类型匹配。 析构表达式将每个参数的值分配给 Deconstruct
方法中相应 out
参数的值。 如果多个 Deconstruct
方法与析构表达式匹配,编译器会报告歧义错误。
以下代码声明具有两个 Deconstruct
方法的 Point3D
结构:
public struct Point3D
{
public int X { get; set; }
public int Y { get; set; }
public int Z { get; set; }
public void Deconstruct(out int x, out int y, out int z)
{
x = X;
y = Y;
z = Z;
}
public void Deconstruct(out int x, out int y)
{
x = X;
y = Y;
}
}
第一种方法支持提取所有三个轴值的析构表达式:X
、Y
和 Z
。 第二种方法仅支持析构平面值:X
和 Y
。 第一种方法的 arity 为 3;第二种方法的 arity 为 2。
上一部分介绍了 Deconstruct
类型的编译器合成 record
方法,该方法带有一个主构造函数。 可以在记录类型中声明更多 Deconstruct
方法。 这些方法可以添加其他属性、删除一些默认属性或两者。 还可以声明与编译器合成签名匹配的 Deconstruct
。 如果声明这样的 Deconstruct
方法,编译器不会合成一个。
只要编译器可以确定解构表达式的唯一 Deconstruct
方法,就可以允许多个 Deconstruct
方法。 通常,同一类型的多个 Deconstruct
方法具有不同数量的参数。 还可以创建多个因参数类型而异的 Deconstruct
方法。 但是,在许多情况下,过多的 Deconstruct
方法可能会导致歧义错误和误导性结果。
C# 语言规范
有关详细信息,请参阅 C# 标准的析构部分。