Andrey on .NET | C# 7 – Деконструкция

C# 7 – Деконструкция

C# logoОдна из новых возможностей, появившихся в 7 версии C#, это деконструкция объекта. Она позволяет быстро разобрать его экземпляр на отдельные переменные, иногда скрывая даже сам факт существования объекта. Кортежи поддерживают ее изначально, а для своих классов ее можно легко добавить. Разберемся подробнее.

Формат записи

Как уже было отмечено, при помощи деконструкции можно легко скопировать значения свойств объекта в отдельные переменные. Запись выглядит следующим образом:

(Type1 var1, Type2 var2, ..., TypeN varN) = obj; // базовый вариант
var (var1, var2, ..., varN) = obj; // вариант записи с var для всех переменных
(var1, var2, ..., varN) = obj; // вариант с использованием ранее объявленных переменных

где:

  • Type1 … TypeN – типы переменных (поддерживается использование var для отдельных переменных).
  • var1 … varN – идентификаторы переменных.
  • obj – объект, поддерживающий операцию деконструкции.

Стоит отметить следующее:

  • Порядок переменных при деконструкции определяется в типе исходного объекта obj и не может быть изменен.
  • Если какие-то из значений не требуются, то вместо них можно использовать подстановку "_" для того, чтобы не объявлять ненужные переменные.

Примеры:

(int id, string name, var status) = person;
var (firstName, lastName, middleName) = GetPersonData(id); // деконструкция результата метода
(_, lastName, _) = GetPersonData(id); // нужно только значение lastName, переменная была объявлена ранее

Деконструкция кортежей

Кортежи (новый Tuple) изначально поддерживают деконструкцию. Порядок переменных соответствует порядку объявления его свойств:

// Объявляем метод, возвращающий Tuple
public (string firstName, string lastName, string middleName) GetUserName(int id) { … }
…  
// Деконструкция кортежа 
(string fn, string ln, string mn) = GetUserName(id);

Создание типов с поддержкой деконструкции

Чтобы тип поддерживал деконструкция, необходимо реализовать в нем следующий метод:

public void Deconstruct(out Type1 var1, ..., out TypeN varN) { … }
  • Порядок следования аргументов Deconstruct(…) определяет порядок переменных при деконструкции.
  • Можно определить несколько различных деконструкторов с различным набором параметров.
  • При работе с интерфейсами необходимо чтобы методы Deconstruct(…) были определены в ��их.

Пример:

public interface IPerson
{
    string FirstName { get; set; }
    string LastName { get; set; }
    string MiddleName { get; set; }

    // Определяем деконструкторы
    void Deconstruct(out string firstName, out string lastName, out string middleName); 
    void Deconstruct(out string firstName, out string lastName);
}
 
// Реализация интерфейса 
public class Person : IPerson { … }

// Использование деконструкторов IPerson 
IPerson person = new Person();
…
(string fn1, string ln1, string mn1) = person;
(string fn2, string ln2) = person;

Добавить комментарий