Использует ли оператор `` ?? `` короткое замыкание? - PullRequest
8 голосов
/ 23 июня 2010

Использует ли оператор ?? в C # короткое замыкание при оценке?

var result = myObject ?? ExpressionWithSideEffects();

Когда myObject не равен нулю, результат ExpressionWithSideEffects() не используется, но ExpressionWithSideEffects() будетполностью пропущен?

Ответы [ 3 ]

10 голосов
/ 23 июня 2010

Да, это делает короткое замыкание.

Вот фрагмент кода для тестирования в LinqPad:

string bar = "lol";
string foo = bar ?? string.Format("{2}", 1);
foo.Dump();
bar = null;
foo = bar ?? string.Format("{2}", 1);
foo.Dump();

Первая операция объединения работает без выброса исключения, а вторая - (форматстрока недействительна).

7 голосов
/ 23 июня 2010

Да, это так.Как всегда, спецификация языка C # является окончательным источником 1 .

Из спецификации C # 3, раздел 7.12 (v3, а не 4, поскольку спецификация v4 входит в динамические детали, которые не 'здесь действительно актуально):

Тип выражения a ?? b зависит от того, какие неявные преобразования доступны между типами операндов.В порядке предпочтения, типb - это A0, A или B, где A - это тип a, B - это тип b (при условии, что b имеет тип), а A0 - базовый тип A, если A - обнуляемый тип, или A в противном случае,В частности, a ?? b обрабатывается следующим образом:

  • Если A не является обнуляемым типом или ссылочным типом, возникает ошибка времени компиляции.
  • Если A является обнуляемым типоми существует неявное преобразование из b в A0, тип результата - A0.Во время выполнения a сначала оценивается.Если a не нуль, a разворачивается к типу A0, и это становится результатом.В противном случае b вычисляется и преобразуется в тип A0, и это становится результатом.
  • В противном случае, если существует неявное преобразование из b в A, типом результата является A. Во время выполнения сначала оценивается a,Если a не нуль, a становится результатом.В противном случае b вычисляется и преобразуется в тип A. И это становится результатом.
  • В противном случае, если b имеет тип B и существует неявное преобразование из A0 в B, тип результата - B.время, а впервые оценивается.Если a не является нулем, a разворачивается в тип A0 (если A и A0 не имеют одинаковый тип) и преобразуется в тип B, и это становится результатом.В противном случае b вычисляется и становится результатом.
  • В противном случае a и b несовместимы, и возникает ошибка времени компиляции.

Второй, третий и четвертыйсоответствующие маркеры.


1 Необходимо провести философскую дискуссию о том, является ли используемый вами компилятор фактическим источником истины... правда ли язык о том, что означало делать или что он в настоящее время делает ?

0 голосов
/ 23 июня 2010

Именно поэтому у нас есть модульное тестирование.

    [TestMethod]
    public void ShortCircuitNullCoalesceTest()
    {
        const string foo = "foo";
        var result = foo ?? Bar();
        Assert.AreEqual(result, foo);
    }

    [TestMethod]
    [ExpectedException(typeof(ArgumentException))]
    public void ShortCircuitNullCoalesceFails()
    {
        const string foo = null;
        var result = foo ?? Bar();
    }

    private static string Bar()
    {
        throw new ArgumentException("Bar was called");
    }

Это не лучшие названия тестов, но вы поняли идею.Он показывает, что операторы слияния нулевого слияния, как и ожидалось, ожидаются.

...