4

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

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 来评估的。而是开始深度。

这是众所周知的事情吗?我能够通过添加括号来完成这项工作,但我真的没想到事情会以这种方式工作。

4

5 回答 5

9

不,这不是错误。这是指定的优先顺序- 二元-运算符的优先级高于??,因此您的代码实际上是:

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;
于 2011-06-07T14:35:46.713 回答
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,而不是 a + (b + c)。在普通算术中,这两个表达式总是给出相同的结果;在计算机算术中,它们不一定。(作为练习,您能否找到 a、b、c 的值,使得 (a + b) + c 不等于 C# 中的 a + (b + c)?)

评估顺序

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

于 2011-06-07T14:44:36.060 回答
0

这完全取决于语言中设置的运算符优先级。IIRC ? 和 ??具有相当低的优先级。

于 2011-06-07T14:33:31.840 回答
0

从不同运算符的优先顺序可以看出,空合并远低于-or *

于 2011-06-07T14:35:21.357 回答
0

我认为这是括号的问题....试试这个:

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

高温高压

于 2011-06-07T14:36:29.937 回答