Что означают два знака вопроса вместе в C #?

Наткнулся на эту строку кода:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

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

вопрос задан 15.01.2009
Edward Tanguay
77610 репутация

16 ответов


  • 1836 рейтинг

    Это оператор слияния null, очень похожий на троичный (немедленный, если) оператор. Смотрите также ? ? Оператор - 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 за указание на это. )

    ответ дан lc., с репутацией 86718, 15.01.2009
  • 235 рейтинг

    Только потому, что никто еще не произнес волшебные слова: это нуль-оператор . Это определено в разделе 7. 12 из C # 3. 0 спецификация языка .

    Это очень удобно, особенно из-за того, как он работает, когда он используется в выражении несколько раз. Выражение формы:

    a ?? b ?? c ?? d
    

    выдаст результат выражения a, если он не равен нулю, в противном случае попробуйте b, в противном случае попробуйте c, в противном случае попробуйте d. Это короткое замыкание в каждой точке.

    Кроме того, если тип d не обнуляется, тип целого выражения также не обнуляется.

    ответ дан Jon Skeet, с репутацией 1057123, 15.01.2009
  • 65 рейтинг

    Это нулевой оператор объединения.

    http: // msdn. Microsoft. ком / EN-US / библиотека / ms173224. aspx

    Да, поиск почти невозможен, если вы не знаете, как он называется! :-)

    РЕДАКТИРОВАТЬ: И это отличная особенность из другого вопроса. Вы можете связать их

    Скрытые возможности C #?

    ответ дан Iain Holder, с репутацией 10583, 15.01.2009
  • 22 рейтинг

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

    // y = x, unless x is null, in which case y = -1.
    int y = x ?? -1;
    
    ответ дан Edward Tanguay, с репутацией 77610, 15.01.2009
  • 17 рейтинг

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

    ответ дан RedFilter, с репутацией 131502, 15.01.2009
  • 15 рейтинг

    enter image description here

    Два знака вопроса (? ? ) указывают, что это оператор объединения.

    Оператор объединения возвращает первое значение NON-NULL из цепочки. Вы можете увидеть это видео на YouTube , которое демонстрирует практически все это.

    Но позвольте мне добавить больше к тому, что говорит видео.

    Если вы видите английское значение объединения, оно говорит: «объединяйтесь». Например, ниже приведен простой объединяющий код, который объединяет четыре строки.

    Таким образом, если str1 равен null, он попытается str2, если str2 равен null, он будет пытаться str3 и так далее, пока не найдет строку с ненулевым значением.

    string final = str1 ?? str2 ?? str3 ?? str4;
    

    Проще говоря, оператор Coalescing возвращает первое значение NON-NULL из цепочки.

    ответ дан Shivprasad Koirala, с репутацией 15205, 16.12.2013
  • 9 рейтинг

    Это короткая рука для троичного оператора.

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

    Или для тех, кто не делает троичный:

    if (formsAuth != null)
    {
      FormsAuth = formsAuth;
    }
    else
    {
      FormsAuth = new FormsAuthenticationWrapper();
    }
    
    ответ дан Benjamin Autin, с репутацией 3641, 15.01.2009
  • 9 рейтинг

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

    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";
    
    ответ дан Sarah Vessels, с репутацией 14002, 30.06.2009
  • 8 рейтинг

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

    КОД

    int x = x1 ?? x2 ?? x3 ?? x4 ?? 0;
    
    ответ дан dqninh, с репутацией 81, 21.03.2013
  • 8 рейтинг

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

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

    в объекте:

    ? anArgument
        ^ self
    

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

    ? anArgument
        ^ anArgument
    

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

    ответ дан blabla999, с репутацией 2896, 15.01.2009
  • 7 рейтинг

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

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

    FormsAuth = formsAUth == null ? new FormsAuthenticationWrapper() : formsAuth
    
    ответ дан aku, с репутацией 96429, 15.01.2009
  • 6 рейтинг

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

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

    return _formsAuthWrapper = _formsAuthWrapper ?? new FormsAuthenticationWrapper();
    

    или

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

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

    ответ дан KingOfHypocrites, с репутацией 4537, 12.05.2014