Знак вопроса (?) в C#

Довольно часто при работе с C# мы можем встретить в коде знак вопроса «?».  Ответ на вопрос «Что означает символ ? в C#?» в значительной степени зависит от того, в каком месте программного кода символ вопроса установлен. Например знак вопроса можно встретить после типа данных, после имени экземпляра класса, в условных выражениях и т.д. В этой заметке я решил собрать основные способы использования символа вопроса (?) в C#.

Знак ? в тернарных операциях C#. Оператор ?:

Про тернарные операции в C# (сокращенная проверка) мы узнали вот из этой статьи. Здесь вопрос ставится сразу после условия, которое необходимо проверить. Например:

int i  = 3;
string s = (i % 2 == 0) ? $"{i} - четное число" : $"{i} - нечетное число";

в тернарной операции знак вопроса (?) используется в паре с двоеточием (:) и читается код выше следующим образом: если остаток от деление числа на два равен нулю, то число четное, иначе — нечетное.

Знак ? в NULL-условных операторах ?. и ?[]

Эти операторы появились впервые в C# 6 и применяются для доступа к членам, ?., или доступа к элементам, ?[] операнда только в том случае, если он имеет значение, отличное от NULL, в противном случае он возвращает null.

Например, у нас есть класс Building и объект (экземпляр класса) — house. Нам необходимо получить доступ к какому-либо свойству этого объекта, однако, мы не можем быть на 100% уверены, что объект проинициализирован, то есть не равен null. Если мы напишем свой код, например, вот так:

width = house.width;

то не факт, что мы получим значение свойства, а не исключение. И здесь нам на помощь может прийти либо условный оператор if , что потребует от нас лишней «писанины», либо тернарная операция, что ненамного сократит код, например:

width = house != null ? house.width : null

или же NULL-условный оператор, как показано ниже:

width = house?.width

Согласитесь, что в последнем случае код стал намного короче. Не могу сказать, что понятнее с первого взгляда (особенно, если вы новичок в C#), но короче — явно. Использование этого оператора — дело привычки и со временем начинаешь очень быстро отслеживать такой оператор в коде.

Работает NULL-условный оператор следующим образом:

Если house вычисляется как null, то результатом house?.width является null.
Если house принимает значение, отличное от NULL, то результат house?.width совпадает с результатом house.width.

Аналогичным образом работает и оператор ?[].

Знак ? в операторе объединения с NULL ??

Ещё один оператор C# в котором используется знак вопроса (?) и, при чем, дважды. Оператор объединения с NULL ?? возвращает значение своего операнда слева, если его значение не равно null. В противном случае он вычисляет операнд справа и возвращает его результат.

Например, рассмотрим вариант использования оператора ?? в связке с NULL-условным оператором. В выражениях с NULL-условным оператором ?. или ?[] можно использовать null, чтобы задать альтернативное выражение для оценки на случай, если результат выражения с NULL-условной операцией будет равен ??.

double SumNumbers(List<double[]> setsOfNumbers, int indexOfSetToSum)
{
    return setsOfNumbers?[indexOfSetToSum]?.Sum() ?? double.NaN;
}

var sum = SumNumbers(null, 0);
Console.WriteLine(sum);  // output: NaN

Здесь в примере в качестве параметров метода SumNumbers задается список наборов чисел и индекс набора в этом списке. Функция должна вернуть сумму чисел или значение NaN. Вначале применяется оператор ?[], если проверка проходит успешно (setsOfNumbers?[indexOfSetToSum] не равен null), то осуществляется следующая проверка с использованием оператора ?. Если и вторая проверка прошла успешна, то вычисляется сумма. Если какая-либо из проверок вернет нам null, то результатом функции будет NaN.

Знак ? в операторе присваивания объединения со значением NULL ??=

Этот оператор появился впервые в C# 8.0.  Оператор ??= используется для присваивания значения правого операнда левому операнду только в том случае, если левый операнд принимает значение null. Оператор ??= не выполняет оценку своего операнда справа, если его операнд слева имеет значение, отличное от NULL.

Знак ? справа от типа. Типы значений, допускающие значение NULL (обнуляемые типы)

Довольно часто в различных пакетах C# можно встретить знак вопроса справа от типа данных, например, в стандартном классе Convert:

public static bool ToBoolean(string? value);

или

public static char ToChar(object? value);

а можно встретить и такую запись:

public short? au_ord;

Что означает знак вопроса рядом с типом, а точнее, справа от типа данных? Означает это, что перед нами тип значения, которому можно присвоить значение null. До сих пор мы были уверены (и так оно и есть), что такие типы данных как int, bool или, например, double не могут принимать значение null. Если же справа от типа стоит знак вопроса, то перед нами тип данных, который допускает значение null.

Обнуляемые типы — это экземпляры структуры System.Nullable. При этом, обнуляемый тип может представлять правильный диапазон значений для своего базового типа значения, а также дополнительное нулевое значение (null). Например, Nullable<Int32>, произносится как «Nullable of Int32», может быть присвоено любое значение от -2147483648 до 2147483647, или ему может быть присвоено нулевое значение. Следующие два определения переменной будут эквивалентны:

int? i  = null;
Nullable<int> i = null;

Обнуляемые типы удобно использовать при работе с базами данных, когда поле таблицы может принимать значение, например, true/false, а может быть и не определено, то есть иметь значение null.

Итого

В C# символ ?, видимо, по праву можно считать одним из самых часто используемых символов в языковых конструкциях. Чтобы понять, для чего конкретно применяется символ вопроса необходимо, как минимум определить где он стоит (справа от типа данных, справа от имени объекта и т.д.). Например, если символ вопроса стоит справа от типа данных, то это значит, что перед нами обнуляемый тип данных.

Подписаться
Уведомить о
guest
4 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии