Язык программирования C#9 и платформа .NET5
Обратите внимание, что при назначении имен в правой части оператора должно использоваться ключевое слово
для объявления переменной. Установка типов данных специальным образом (даже без специфических имен) заставляет компилятор применять синтаксис в левой части оператора, назначать свойствам имена согласно системе обозначенийvarи игнорировать имена, указанные в правой части. В следующих двух операторах именаItemXиCustom1игнорируются:Custom2(int, int) example = (Custom1:5, Custom2:7);(int Field1, int Field2) example = (Custom1:5, Custom2:7);Важно также понимать, что специальные имена полей существуют только на этапе компиляции и не доступны при инспектировании кортежа во время выполнения с использованием рефлексии (рефлексия раскрывается в главе 17).
Кортежи также могут быть вложенными как кортежи внутри кортежей. Поскольку с каждым свойством в кортеже связан тип данных, и кортеж является типом данных, следующий код полностью законен:
Console.WriteLine("=> Nested Tuples");var nt = (5, 4, ("a", "b"));Использование выведенных имен переменных (обновление в версии C# 7.1)
В C# 7.1 появилась возможность выводить имена переменных кортежей, как показано ниже:
Console.WriteLine("=> Inferred Tuple Names");var foo = new {Prop1 = "first", Prop2 = "second"};var bar = (foo.Prop1, foo.Prop2);Console.WriteLine($"{bar.Prop1};{bar.Prop2}");Понятие эквивалентности/неэквивалентности кортежей (нововведение в версии 7.3)
Дополнительным средством в версии C# 7.1 является эквивалентность (
) и неэквивалентность (==) кортежей. При проверке на неэквивалентность операции сравнения будут выполнять неявные преобразования типов данных внутри кортежей, включая сравнение допускающих и не допускающих!=кортежей и/или свойств. Это означает, что следующие проверки нормально работают, несмотря на разницу междуnullиint:longConsole.WriteLine("=> Tuples Equality/Inequality");// Поднятые преобразованияvar left = (a: 5, b: 10);(int? a, int? b) nullableMembers = (5, 10);Console.WriteLine(left == nullableMembers); // Тоже True// Преобразованным типом слева является (long, long)(long a, long b) longTuple = (5, 10);Console.WriteLine(left == longTuple); // Тоже True// Преобразования выполняются с кортежами (long, long)(long a, int b) longFirst = (5, 10);(int a, long b) longSecond = (5, 10);Console.WriteLine(longFirst == longSecond); // Тоже TrueКортежи, которые содержат кортежи, также можно сравнивать, но только если они имеют одну и ту же форму. Нельзя сравнивать кортеж с тремя свойствами
и кортеж, содержащий два свойстваintплюс кортеж.intИспользование отбрасывания с кортежами
Ранее в главе для возвращения из вызова метода более одного значения применялись параметры
. Для этого существуют другие способы вроде создания класса или структуры специально для возвращения значений. Но если такой класс или структура используется только в целях передачи данных для одного метода, тогда нет нужды выполнять излишнюю работу и писать добавочный код. Кортежи прекрасно подходят для решения задачи, т.к. они легковесны, просты в объявлении и несложны в применении.outНиже представлен один из примеров, рассмотренных в разделе о параметрах
. Методoutвозвращает три значения, но требует использования в вызывающем коде трех параметров как механизма передачи:FillTheseValues()static void FillTheseValues(out int a, out string b, out bool c){a = 9;b = "Enjoy your string.";c = true;}За счет применения кортежа от параметров можно избавиться и все равно получать обратно три значения:
static (int a,string b,bool c) FillTheseValues(){return (9,"Enjoy your string.",true);}Вызывать новый метод не сложнее любого другого метода:
var samples = FillTheseValues();Console.WriteLine($"Int is: {samples.a}");Console.WriteLine($"String is: {samples.b}");Console.WriteLine($"Boolean is: {samples.c}");Возможно, даже лучшим примером будет разбор полного имени на отдельные части (имя (
), отчество (first), фамилия (middle)). Следующий методlastполучает полное имя и возвращает кортеж с составными частями:SplitNames()static (string first, string middle, string last) SplitNames(string fullName){// Действия, необходимые для расщепления полного имени.return ("Philip", "F", "Japikse");}Использование отбрасывания с кортежами
Продолжим пример с методом
. Пусть известно, что требуются только имя и фамилия, но не отчество. В таком случае можно указать имена свойств для значений, которые необходимо возвращать, а ненужные значения заменить заполнителем в виде подчеркивания (SplitNames()):_