C# 7 – Кортежи (обновленный тип Tuple)

C# logo
Одно из улучшений C#7 коснулось работы с кортежами, которые представлены типом Tuple. Ранее их использование было не очень популярно по двум причинам:
  • относительная громоздкость конструкции;
  • низкая читабельность кода из-за стандартных, ни о чем не говорящих имен свойств Item1ItemN.
Зачастую вместо Tuple создавался отдельный класс, что увеличивало объем кода. В других случаях использовались выходные параметры (out), но это делало сами методы неудобными для использования. С# 7 устраняет указанные недостатки. Для примера возьмем код с Tuple и улучшим его:

public Tuple<double, double> GetCoords()
{
    // ...
    return new Tuple<double, double>(valueX, valueY);
}

Использование нового варианта Tuple требует установки NuGet пакета System.ValueTuple. Важно отметить, что старый и новый Tuple это различные типы.

Возможности C# 7 позволяют:

  • использовать сокращенную запись, указав в круглых скобках используемые типы при определении и значения при создании экземпляра Tuple;
  • дополнительно можно задать имена свойств (при этом IntelliSense использует их в подсказках при выборе свойств).
public (double X, double Y) GetCoords()
{
    // ...
    return (valueX, valueY);
}

Обратите внимание на отсутствие ключевого слова new при создании экземпляра Tuple.

При этом дополнительно доступны:

  • обратная совместимость: к свойствам по прежнему можно обращаться по именам Item1ItemN.
  • возможность использования деконструкции для переопределения имен свойств.

Код из примера выше можно использовать следующим образом:

// 1) Используем Item1 ... ItemN  var coords = map.GetCoords0();
this.ProcessCoods(coords.Item1, coords.Item2);
 
// 2) Используем имена свойств
var coords = map.GetCoords2();
this.ProcessCoods(coords.X, coords.Y);
 
// 3) Деконструкция в отдельные переменные с указанием типов
(double x, double y) = map.GetCoords0();
this.ProcessCoods(x, y);
 
// 4) Деконструкция в отдельные переменные с использованием var
var(x, y) = map.GetCoords0();
this.ProcessCoods(x, y);

Обратите внимание, что варианты с деконструкцией (3) и (4) так же можно можно использовать и со старым Tuple.

Комментарии (2) -

Я вот боюсь что после этого люди начнут активно использовать кортежи не по месту.
Вот у нас в коде есть Pair<int,long> вместо нормального документируемого класса.
А теперь будет больше безымянныхSmile
Хорошо бы имена добавить в обобщения типа
Dictionary<string Address, Dictionary<string Name, int Age>>>
И работало бы как новые кортежи.

NN Если класс не большой, используется только локально (или вообще private внутри другого), то я не вижу проблемы. Плюс, для таких классов имена свойств зачастую и есть документация (те же DTO, которые просто являются контейнерами для данных).

В общем, как по мне, так позитивного тут больше.

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