我从这个方法得到了奇怪的结果:
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。
这是一个众所周知的事吗?我能够通过添加括号来完成这项工作,但我真的不希望事情以这种方式工作。
答案 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