условные - тернарный оператор c#




Что означают два знака вопроса в C#? (11)

Замечания:

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

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

Источник:

Основы коммуникаций Windows, выпущенные Craig McMurtry ISBN 0-672-32948-4

Типы недопустимых значений

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

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

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, которое в действительности было бы в этом случае, и это значение не может быть присвоено обычному типу значений. Хотя компилятор разрешил бы этот код,

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.

Пробег через эту строку кода:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

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


Если вы знакомы с Ruby, его ||= кажется сродни C # ?? мне. Вот некоторые Ruby:

irb(main):001:0> str1 = nil
=> nil
irb(main):002:0> str1 ||= "new value"
=> "new value"
irb(main):003:0> str2 = "old value"
=> "old value"
irb(main):004:0> str2 ||= "another new value"
=> "old value"
irb(main):005:0> str1
=> "new value"
irb(main):006:0> str2
=> "old value"

И в C #:

string str1 = null;
str1 = str1 ?? "new value";
string str2 = "old value";
str2 = str2 ?? "another new value";

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

Вы действительно хотите:

return _formsAuthWrapper = _formsAuthWrapper ?? new FormsAuthenticationWrapper();

или же

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

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


Ничего опасного в этом нет. На самом деле это красиво. Вы можете добавить значение по умолчанию, если это желательно, например:

КОД

int x = x1 ?? x2 ?? x3 ?? x4 ?? 0;

Спасибо всем, вот самое краткое объяснение, которое я нашел на сайте MSDN:

// y = x, unless x is null, in which case y = -1.
int y = x ?? -1;

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

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

в объекте:

? anArgument
    ^ self

в UndefinedObject (класс aka nil):

? anArgument
    ^ anArgument

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


Это нулевой коалесцирующий оператор и совсем как трёхмерный (немедленный-if) оператор. См. Также ? Оператор - MSDN .

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

расширяется до:

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

который далее расширяется до:

if(formsAuth != null)
    FormsAuth = formsAuth;
else
    FormsAuth = new FormsAuthenticationWrapper();

На английском языке это означает: «Если все, что слева, не пустое, используйте это, иначе используйте то, что справа».

Обратите внимание, что вы можете использовать любое количество из них в последовательности. Следующий оператор присваивает первому ненулевому Answer# Answer (если все ответы равны нулю, тогда Answer равен нулю):

string Answer = Answer1 ?? Answer2 ?? Answer3 ?? Answer4;

Также стоит упомянуть, в то время как расширение выше концептуально эквивалентно, результат каждого выражения оценивается только один раз. Это важно, если, например, выражение представляет собой вызов метода с побочными эффектами. (Подпишитесь на @Joey, чтобы указать на это.)



коалесцирующий оператор

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

FormsAuth = formsAUth == null ? new FormsAuthenticationWrapper() : formsAuth

?? существует ли значение для типа с нулевым значением, когда значение равно null. Итак, если formsAuth имеет значение null, он вернет новый FormsAuthenticationWrapper ().


FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

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

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

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

A = A ?? B ?? throw new Exception("A and B are both NULL");






null-coalescing-operator