null合并操作顺序

时间:2011-06-07 14:31:16

标签: c# .net null null-coalescing-operator

我从这个方法得到了奇怪的结果:

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

当我将null传递给StartDepth时,合并失败,因为正在评估“Depth - StartDepth”,首先将StartDepth转换为默认值0(降级?)而不是先查看它是否为null并替换为相反,Globals.StartDepth。

这是一个众所周知的事吗?我能够通过添加括号来完成这项工作,但我真的不希望事情以这种方式工作。

5 个答案:

答案 0 :(得分:7)

不,这不是错误。它是specified order of precedence - 二进制-运算符的优先级高于??,因此您的代码是有效的:

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;

答案 1 :(得分:3)

作为@Jon Skeet,这是一个优先问题,可以通过用括号明确定义正确的优先级来解决。 (例如(Depth - (StartDepth ?? Globals.StartDepth)) * PrintScale ?? Constants.YPixelsPerUnit;

这个概念并不是很明显,优先级关联性评估顺序在C#中的工作方式并不总是直观的。

Eric Lippert在他的文章Precedence vs Associativity vs Order中非常好地解释了这些概念。我强烈建议阅读那篇文章。以下是最关键的摘录:

优先级

优先规则描述了当表达式混合不同类型的运算符时,如何将表示不足的表达式括起来。例如,乘法的优先级高于加法,因此2 + 3 x 4相当于2 +(3 x 4),而不是(2 + 3)x 4。

结合性

关联性规则描述了当表达式具有一堆相同类型的运算符时,如何将表示不足的表达式括起来。例如,加法从左到右是关联的,因此a + b + c等价于(a + b)+ c,而不是+(b + c)。在普通算术中,这两个表达式总是给出相同的结果;在计算机算术中,它们不一定。 (作为练习,您可以找到a,b,c的值,使得(a + b)+ c在C#中不等于+(b + c)?)

评估顺序

评估规则的顺序描述了表达式中每个操作数的计算顺序。括号只描述结果如何组合在一起; “先做括号”不是C#的规则。相反,C#中的规则是“严格从左到右评估每个子表达式”。

答案 2 :(得分:0)

这一切都取决于语言中设置的operator precedence。 IIRC?和??优先级很低。

答案 3 :(得分:0)

从不同运算符的order of precedence可以看出,空合并比-*低得多。

答案 4 :(得分:0)

我认为括号中存在问题....试试这个:

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

HTH