TesterMethod(null);
В языке C# имеется маркер null-условной операции (знак вопроса, находящийся после типа переменной, но перед операцией доступа к члену), который позволяет упростить представленную ранее проверку на предмет null. Вместо явного условного оператора, проверяющего на неравенство значению null, теперь можно написать такой код:
static void TesterMethod(string[] args)
{
// Мы должны проверять на предмет null перед доступом к данным массива!
Console.WriteLine($"You sent me {args?.Length} arguments.");
}
В этом случае условный оператор не применяется. Взамен к переменной массива string в качестве суффикса добавлена операция ?. Если переменная args равна null, тогда обращение к свойству Length не приведет к ошибке во время выполнения. Чтобы вывести действительное значение, можно было бы воспользоваться операцией объединения с null и установить стандартное значение:
Console.WriteLine($"You sent me {args?.Length ?? 0} arguments.");
Существуют дополнительные области написания кода, в которых null-условная операция окажется очень удобной, особенно при работе с делегатами и событиями. Данные темы раскрываются позже в книге (см. главу 12) и вы встретите еще много примеров.
Понятие кортежей (нововведение и обновление в версии 7.0)
В завершение главы мы исследуем роль кортежей, используя проект консольного приложения по имени FunWithTuples. Как упоминалось ранее в главе, одна из целей применения параметров out — получение более одного значения из вызова метода. Еще один способ предусматривает использование конструкции под названием кортежи.
Кортежи, которые являются легковесными структурами данных, содержащими множество полей, фактически появились в версии C# 6, но применяться могли в крайне ограниченной манере. Кроме того, в их реализации C# 6 существовала значительная проблема: каждое поле было реализовано как ссылочный тип, что потенциально порождало проблемы с памятью и/или производительностью (из-за упаковки/распаковки).
В версии C# 7 кортежи вместо ссылочных типов используют новый тип данных ValueTuple, сберегая значительных объем памяти. Тип данных ValueTuple создает разные структуры на основе количества свойств для кортежа. Кроме того, в C# 7 каждому свойству кортежа можно назначать специфическое имя (подобно переменным), что значительно повышает удобство работы с ними.
Относительно кортежей важно отметить два момента:
• поля не подвергаются проверке достоверности;
• определять собственные методы нельзя.
В действительности кортежи предназначены для того, чтобы служить легковесным механизмом передачи данных.
Начало работы с кортежами
Итак, достаточно теории, давайте напишем какой-нибудь код! Чтобы создать кортеж, просто повестите значения, подлежащие присваиванию, в круглые скобки:
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})
("a", 5, "c")
Обратите внимание, что все значения не обязаны относиться к тому же самому типу данных. Конструкция с круглыми скобками также применяется для присваивания кортежа переменной (или можно использовать ключевое слово var и тогда компилятор назначит типы данных самостоятельно). Показанные далее две строки кода делают одно и то же — присваивают предыдущий пример кортежа переменной. Переменная values будет кортежем с двумя свойствами string и одним свойством int.
(string, int, string) values = ("a", 5, "c");
var values = ("a", 5, "c");
По умолчанию компилятор назначает каждому свойству имя ItemX, где X представляет позицию свойства в кортеже, начиная с 1. В предыдущем примере свойства именуются как Item1, Item2 и Item3. Доступ к ним осуществляется следующим образом:
Console.WriteLine($"First item: {values.Item1}"); // Первый элемент
Console.WriteLine($"Second item: {values.Item2}"); // Второй элемент
Console.WriteLine($"Third item: {values.Item3}"); // Третий элемент
Кроме того, к каждому свойству кортежа справа или слева можно добавить специфическое имя. Хотя назначение имен в обеих частях оператора не приводит к ошибке на этапе компиляции, имена в правой части игнорируются, а использоваться будут имена в левой части. Показанные ниже две строки кода демонстрируют установку имен в левой и правой частях оператора, давая тот же самый результат:
(string FirstLetter, int TheNumber, string SecondLetter)
valuesWithNames = ("a", 5, "c");
var valuesWithNames2 = (FirstLetter: "a", TheNumber: 5, SecondLetter: "c");
Теперь доступ к свойствам кортежа возможен с применением имен полей, а также системы обозначений ItemX:
Console.WriteLine($"First item: {valuesWithNames.FirstLetter}");
Console.WriteLine($"Second item: {valuesWithNames.TheNumber}");
Console.WriteLine($"Third item: {valuesWithNames.SecondLetter}");
// Система обозначений ItemX по-прежнему работает!
Console.WriteLine($"First item: {valuesWithNames.Item1}");
Console.WriteLine($"Second item: {valuesWithNames.Item2}");
Console.WriteLine($"Third item: {valuesWithNames.Item3}");