Что означают два знака вопроса вместе в C #? - PullRequest
1457 голосов
/ 15 января 2009

Пробежал по этой строке кода:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

Что означают два вопросительных знака, это какой-то троичный оператор? Трудно найти в Google.

Ответы [ 17 ]

10 голосов
/ 15 января 2009

оператор коалесцирования

это эквивалентно

FormsAuth = formsAUth == null ? new FormsAuthenticationWrapper() : formsAuth
10 голосов
/ 15 января 2009

Только для вашего развлечения (зная, что вы все ребята из C #; -).

Я думаю, что он возник в Smalltalk, где он существует уже много лет. Там это определяется как:

в объекте:

? anArgument
    ^ self

в UndefinedObject (он же класс nil):

? anArgument
    ^ anArgument

Существуют как оценочные (?), Так и не оценивающие версии (??) этого.
Он часто встречается в методах-получателях для приватных инициализированных переменных (экземпляров), которые оставляются равными нулю до тех пор, пока они действительно не понадобятся.

9 голосов
/ 12 мая 2014

Некоторые примеры получения значений с использованием коалесценции здесь неэффективны.

То, что вы действительно хотите, это:

return _formsAuthWrapper = _formsAuthWrapper ?? new FormsAuthenticationWrapper();

или

return _formsAuthWrapper ?? (_formsAuthWrapper = new FormsAuthenticationWrapper());

Это предотвращает воссоздание объекта каждый раз. Вместо того, чтобы приватная переменная оставалась нулевой, а новый объект создавался при каждом запросе, это гарантирует, что приватная переменная будет назначена при создании нового объекта.

7 голосов
/ 14 марта 2017

Примечание:

Я прочитал всю эту ветку и многие другие, но не могу найти столь подробный ответ, как этот.

По которому я полностью понял, «зачем использовать ?? и когда использовать ?? и как использовать ??.»

* Источник: 1010 *

Основа коммуникации Windows выпущена Крейгом МакМертри ISBN 0-672-32948-4

Типы значений Nullable

Есть два распространенных обстоятельства, при которых один хотел бы знать, значение было присвоено экземпляру типа значения. Первый - это когда экземпляр представляет значение в базе данных. В таком случае хотелось бы иметь возможность изучить экземпляр, чтобы выяснить, действительно ли значение присутствует в базе данных. Другое обстоятельство, которое в большей степени относится к предмету этой книги, - это когда экземпляр представляет элемент данных, полученный из некоторого удаленного источника. Опять же, из этого экземпляра хотелось бы определить, было ли получено значение для этого элемента данных.

.NET Framework 2.0 включает определение универсального типа, которое обеспечивает случаи, подобные этим, в которых требуется присвоить значение NULL экземпляру типа значения, и проверить, является ли значение экземпляра NULL. Это определение универсального типа - System.Nullable, которое ограничивает аргументы универсального типа, которые могут быть заменены на T, значениями типов. Экземплярам типов, созданным из System.Nullable, может быть присвоено значение null; действительно, их значения по умолчанию равны нулю. Таким образом, типы построены из System.Nullable может упоминаться как типы значений Nullable. System.Nullable имеет свойство Value, с помощью которого значение, присвоенное экземпляру построенный из него тип может быть получен, если значение экземпляра не равно нулю. Поэтому можно написать:

System.Nullable<int> myNullableInteger = null;
myNullableInteger = 1;
if (myNullableInteger != null)
{
Console.WriteLine(myNullableInteger.Value);
}

Язык программирования C # предоставляет сокращенный синтаксис для объявления типов построен из System.Nullable. Этот синтаксис позволяет сокращать:

System.Nullable<int> myNullableInteger;

до

int? myNullableInteger;

Компилятор предотвратит попытку присвоения значения типа значения NULL для обычного типа значения следующим образом:

int? myNullableInteger = null;
int myInteger = myNullableInteger;

Он запрещает это делать, потому что тип значения, допускающий значение NULL, может иметь значение NULL, которое в действительности будет иметь в этом случае, и это значение не может быть присвоено обычному типу значения. Хотя компилятор разрешил бы этот код,

int? myNullableInteger = null;
int myInteger = myNullableInteger.Value;

Второе утверждение вызовет исключение, потому что любая попытка Доступ к свойству System.Nullable.Value является недопустимой операцией, если тип построенный из System.Nullable не было назначено допустимое значение T, что не произошло в этом случае.

Вывод:

Один из правильных способов присвоения значения типа значения NULL для обычного типа значения - это использование свойства System.Nullable.HasValue, чтобы определить, было ли назначено допустимое значение T для типа NULL:

int? myNullableInteger = null;
if (myNullableInteger.HasValue)
{
int myInteger = myNullableInteger.Value;
}

Другой вариант - использовать этот синтаксис:

int? myNullableInteger = null;
int myInteger = myNullableInteger ?? -1;

С помощью которого обычному целому числу myInteger присваивается значение обнуляемого целого числа «myNullableInteger», если последнему было присвоено действительное целочисленное значение; в противном случае myInteger присваивается значение -1. ​​

1 голос
/ 06 февраля 2019

Оператор ?? называется оператором слияния нуля. Возвращает левый операнд, если операнд не равен нулю; в противном случае возвращается правый операнд.

int? variable1 = null;
int variable2  = variable1 ?? 100;

Установите variable2 на значение variable1, если variable1 НЕ равно нулю; в противном случае, если variable1 == null, установите variable2 на 100.

1 голос
/ 01 апреля 2018
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

эквивалентно

FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();

Но крутая вещь в том, что вы можете связать их, как говорили другие люди Один тонкий момент, который не затрагивается, заключается в том, что вы можете использовать его для создания исключения.

A = A ?? B ?? throw new Exception("A and B are both NULL");
0 голосов
/ 08 декабря 2017

Это нулевой оператор объединения, который работает аналогично троичному оператору.

    a ?? b  => a !=null ? a : b 

Еще один интересный момент для этого, «Обнуляемый тип может содержать значение или может быть неопределенным» . Поэтому, если вы попытаетесь присвоить тип значения, допускающий значение NULL, для типа, не допускающего значения NULL вы получите ошибку во время компиляции.

int? x = null; // x is nullable value type
int z = 0; // z is non-nullable value type
z = x; // compile error will be there.

Так, чтобы сделать это, используя ?? Оператор:

z = x ?? 1; // with ?? operator there are no issues
...