нулевой порядок объединения - PullRequest
4 голосов
/ 07 июня 2011

Я получаю странные результаты от этого метода:

public static double YFromDepth(double Depth, double? StartDepth, double? PrintScale)
{               
    return (Depth - StartDepth ?? Globals.StartDepth) * PrintScale ?? Constants.YPixelsPerUnit ;
}

Когда я передаю нулевое значение в StartDepth, объединение завершается неудачно, потому что "Depth - StartDepth" оценивается по-видимому, сначала преобразовав StartDepth впо умолчанию 0 (понижен?) вместо того, чтобы сначала посмотреть, является ли он нулевым, и вместо этого подставить в Globals.StartDepth.

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

Ответы [ 5 ]

7 голосов
/ 07 июня 2011

Нет, это не ошибка.Это указанный порядок приоритета - бинарный оператор - имеет более высокий приоритет, чем ??, поэтому ваш код эффективен:

return ((Depth - StartDepth) ?? Globals.StartDepth) * 
          PrintScale ?? Constants.YPixelsPerUnit;

Если вы не хотите этот приоритет, вы должны указать это явно:

return (Depth - (StartDepth ?? Globals.StartDepth)) * 
          PrintScale ?? Constants.YPixelsPerUnit;

Лично я бы расширил метод, чтобы сделать его более понятным:

double actualStartDepth = StartDepth ?? Globals.StartDepth;
double actualScale = PrintScale ?? Constants.YPixelsPerUnit;
return (depth - actualStartDepth) * actualScale;
3 голосов
/ 07 июня 2011

Как и @Jon Skeet, эта проблема имеет приоритет и может быть решена путем явного определения правильного приоритета с помощью скобок.(например, (Depth - (StartDepth ?? Globals.StartDepth)) * PrintScale ?? Constants.YPixelsPerUnit;)

Эта концепция не сразу очевидна, и способ приоритет , ассоциативность и порядок оценки работают в C #не всегда интуитивно понятен

Эрик Липперт очень хорошо объясняет эти понятия в своей статье Приоритет против ассоциативности против порядка .Я настоятельно рекомендую прочитать эту статью.Ниже приведены наиболее важные выдержки:

Приоритет

Правила приоритета описывают, как выражение в скобках должно быть заключено в скобки, когда выражение смешивает операторы разных типов.Например, умножение имеет более высокий приоритет, чем сложение, поэтому 2 + 3 x 4 эквивалентно 2 + (3 x 4), а не (2 + 3) x 4.

Ассоциативность

Правила ассоциативности описывают, как выражение, заключенное в скобки, должно заключаться в скобки, когда выражение имеет группу операторов одного типа.Например, сложение ассоциативно слева направо, поэтому a + b + c эквивалентно (a + b) + c, а не a + (b + c).В обычной арифметике эти два выражения всегда дают один и тот же результат;в компьютерной арифметике они не обязательно.(В качестве упражнения вы можете найти значения для a, b, c такие, что (a + b) + c не равно a + (b + c) в C #?)

Порядок оценки

Порядок правил оценки описывает порядок, в котором оценивается каждый операнд в выражении.Скобки просто описывают, как результаты группируются вместе;«делать круглые скобки первыми» не является правилом C #.Скорее, правило в C # «оценивать каждое подвыражение строго слева направо».

0 голосов
/ 07 июня 2011

Я думаю, что это проблема с скобками .... Попробуйте это:

public static double YFromDepth(double Depth, double? StartDepth, double? PrintScale)
{               
    return (Depth - (StartDepth ?? Globals.StartDepth)) * (PrintScale ?? Constants.YPixelsPerUnit) ;
}

НТН

0 голосов
/ 07 июня 2011

Как видно из порядка старшинства различных операторов, нулевая коалесценция намного ниже, чем - или *.

0 голосов
/ 07 июня 2011

Все зависит от того, какой приоритет оператора установлен в языке. IIRC? а также ?? имеют довольно низкий приоритет.

...