当比较两个数字/函数的最小值或最大值时,如果第一个数字/函数的情况为真,并且意味着第二个数字/函数的情况为真,C# 是否会短路?这些情况的具体示例是
if(x < Math.Max(y, z()))
和
if(x > Math.Min(y, z()))
由于如果 x <Math.Min 的情况类似。
我意识到这些都可以按照
if(x < y || x < z())
短路的方式重写,但我认为在不重写的情况下比较更清楚。这个会短路吗?
When comparing to a minimum or maximum of two numbers/functions, does C# short-circuit if the case is true for the first one and would imply truth for the second? Specific examples of these cases are
if(x < Math.Max(y, z()))
and
if(x > Math.Min(y, z()))
Since Math.Max(y, z())
will return a value at least as large as y, if x < y then there is no need to evaluate z(), which could take a while. Similar situation with Math.Min
.
I realize that these could both be rewritten along the lines of
if(x < y || x < z())
in order to short-circuit, but I think it's more clear what the comparison is without rewriting. Does this short-circuit?
发布评论
评论(5)
正如其他人指出的那样,编译器对 Min 或 Max 的语义一无所知,这将允许它打破在调用方法之前评估参数的规则。
如果你想编写自己的代码,你可以很容易地做到这
:然后将其称为
或Or :
一点
As others have pointed out, the compiler knows nothing about the semantics of Min or Max that would allow it to break the rule that arguments are evaluated before the method is called.
If you wanted to write your own, you could do so easily enough:
and then call it
or
Or for that matter:
不,它不会短路,并且 z() 将始终被评估。如果你想要短路行为,你应该像你所做的那样重写。
No, it doesn't short circuit and z() will always be evaluated. If you want the short circuiting behavior you should rewrite as you have done.
Math.Min()
和Math.Max()
是与其他方法一样的方法。必须对它们进行求值才能返回将用作比较中的第二个参数的值。如果您想要短路,那么您必须使用||
运算符编写条件,如您所演示的那样。Math.Min()
andMath.Max()
are methods just like any other. They have to be evaluated in order to return the value which will be used as the second argument in the comparison. If you want short-circuiting then you will have to write the condition using the||
operator as you have demonstrated.(没有什么特别新的内容要添加,但我想我应该分享我在其上运行的测试结果。)
Math.Max() 可以很容易地被 CLR 的即时编译器内联,从那里我很好奇是否它可能会以短路的方式进一步优化代码。
因此,我创建了一个微基准测试,对这两个表达式各评估 1,000,000 次。
对于 z(),我使用了一个使用递归方法计算 Fib(15) 的函数。以下是运行这两个命令的结果:
我猜测 CLR 不会以任何阻止方法调用执行的方式转换代码,因为它不知道(并且不会检查)例程是否有任何副作用。
(Nothing particularly new to add, but I figured I'd share the results of a test I ran on it.)
Math.Max() could easily be inlined by the CLR's just-in-time compiler and from there I was curious whether it might further optimize the code in such a way that it is short-circuited.
So I whipped up a microbenchmark that evaluates the two expressions 1,000,000 times each.
For z(), I used a function that calculates Fib(15) using the recursive method. Here are the results of running the two:
I'm guessing the CLR won't transform the code in any way that prevents method calls from executing, because it doesn't know (and doesn't check to see if) the routine has any side effects.
不,它不会短路,至少在 C# 编译器级别是这样。
Math.Min
或Math.Max
是两个普通的静态方法调用,编译器不会在这个意义上进行优化。代码的求值顺序为:z()、Math.Max、x > ...
如果您确实想确定,请查看 IL 代码。
No, it doesnt short circuit, at least at the C# compiler level.
Math.Min
orMath.Max
are two ordinary static method calls and the compiler will not optimize in that sense.The order of evaluation of the code will be: z(), Math.Max, x > ...
If you really want to make sure, check out the IL code.