Выражение деконструкции - Извлечение свойств полей из кортежа или другого типа, определяемого пользователем
Выражение деконструкции извлекает поля данных из экземпляра объекта. Каждый дискретный элемент данных записывается в отдельную переменную, как показано в следующем примере:
var tuple = (X: 1, Y: 2);
var (x, y) = tuple;
Console.WriteLine(x); // output: 1
Console.WriteLine(y); // output: 2
В предыдущем фрагменте кода создается кортеж , который содержит два целых значения: X
и Y
. Второе выражение деконструирует этот кортеж и сохраняет элементы кортежа в отдельных переменных x
и y
.
Деконструкция кортежа
Все типы кортежей поддерживают выражения деконструкции. Деконструкция кортежа извлекает все элементы кортежа. Если требуется только часть элементов кортежа, используйте "discard" для неиспользуемых элементов кортежа, как показано в примере ниже:
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
должен соответствовать типу соответствующего аргумента в выражении деконструкции. Выражение деконструкции назначает значение каждого аргумента значению соответствующего параметра out
в методе Deconstruct
. Если несколько методов Deconstruct
соответствуют выражению деконструкции, компилятор сообщает об ошибке из-за неоднозначности.
Следующий код объявляет структуру Point3D
с двумя методами Deconstruct
:
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
. Первый метод имеет арность 3, второй имеет арность 2.
В предыдущем разделе описан метод Deconstruct
, созданный компилятором, для типов record
с основным конструктором. Можно объявить больше методов Deconstruct
в типах записей. Эти методы могут добавлять другие свойства, удалять некоторые свойства по умолчанию или оба. Вы также можете объявить Deconstruct
, которая соответствует сигнатуре, сформированной компилятором. Если объявить такой метод Deconstruct
, компилятор не синтезирует его.
Несколько методов Deconstruct
разрешены, если компилятор может определить один уникальный Deconstruct
метод для выражения деконструкции. Как правило, несколько методов Deconstruct
для одного типа имеют разные числа параметров. Можно также создать несколько методов Deconstruct
, которые отличаются типами параметров. Однако во многих случаях слишком большое количество методов Deconstruct
может привести к ошибкам, связанным с неоднозначностью, и вводящим в заблуждение результатам.
Спецификация языка C#
Дополнительные сведения см. в разделе деконструкции C# standard.