Одна из новых возможностей, появившихся в 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;