Содержание
Довольно часто при работе с 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# символ ?
, видимо, по праву можно считать одним из самых часто используемых символов в языковых конструкциях. Чтобы понять, для чего конкретно применяется символ вопроса необходимо, как минимум определить где он стоит (справа от типа данных, справа от имени объекта и т.д.). Например, если символ вопроса стоит справа от типа данных, то это значит, что перед нами обнуляемый тип данных.