C# 有没有可能让编译器自动优化我的“或”语句?

C# 有没有可能让编译器自动优化我的“或”语句?,c#,optimization,C#,Optimization,有没有办法让C编译器优化if语句中的my或子句 例如: if(Function_that_returns_boolean() || boolean_value) { // Do something here... } 执行时间可能与 if(boolean_value || Function_that_returns_boolean()) { // Do something here... } 取决于函数返回的布尔值在内部实际做了多少功 编译器不太可能也不可能确切地知道函数返回

有没有办法让C编译器优化if语句中的my或子句

例如:

if(Function_that_returns_boolean() || boolean_value)
{
    // Do something here...
}
执行时间可能与

if(boolean_value || Function_that_returns_boolean())
{
    // Do something here...
}
取决于函数返回的布尔值在内部实际做了多少功

编译器不太可能也不可能确切地知道函数返回布尔值的效率,我所有的简短测试都表明OR语句总是从左到右处理,即使在使用最激进的编译器优化的情况下也是如此

这是否已经由编译器处理,即我是否弄错了?如果没有,我能给你一些提示吗

也许是一个属性,让编译器知道可以自由地重新排列代码,如果不存在,就让它保留

[OrStatementUsage(Speed.Fast)] // Always push statement left when possible
public bool Fast_function_that_returns_boolean()
{
    return a + b == c; // fast
}

[OrStatementUsage(Speed.Slow)] // Always push statement right when possible
public bool Slow_function_that_returns_boolean()
{
    Thread.Sleep(1000);
    return a + b == c; // slow
}

注意:语句中的所有方法都必须被标记,并且没有副作用,才能作为重新排列的候选者

否,计算第一个参数,如果为真,则根本不计算第二个参数。这被称为短路评估


无法指示编译器计算| | first的第二个参数。

不,布尔逻辑运算符总是进行短路计算。在or的情况下,如果第二部分的计算结果已经为true,那么它甚至可能不会被计算。例如:

if(ReturnTrue() || SlowOperation()) { /* ... */ }

假设ReturnTrue返回true,则永远不会调用SlowOperation。编译器无法基于某些任意假设进行优化

条件OR运算符| |对其布尔操作数执行逻辑OR。如果第一个操作数的计算结果为true,则不计算第二个操作数。如果第一个操作数的计算结果为false,则第二个运算符将确定OR表达式作为一个整体的计算结果是true还是false

将始终计算第一个操作数。这是一个非常重要的保证:

if (obj == null || obj.foo == "bar")
如果编译器可以在这里对条件重新排序,它将改变程序的功能


编译器无法知道给定的重新排序是否会影响结果——这既是因为它通常不知道结果是什么,也是因为它不知道结果的哪些部分是重要的。可能您需要较长的延迟,或者第一次计算对程序的正确性有重要影响。

ctrl-f-circuit@zerkms我不太明白。我理解短路,但我试图通过在语句x中首先计算y来短路||y@Michael:它与您和我的所有简短测试相关,表明或语句总是从左向右处理-因此,它总是从左向右处理。不,这不是由编译器或抖动处理的。他们不可能这样做,调用的方法可能有副作用这一事实不可忽视。@Hans我甚至不必编辑我的问题来提到这些方法需要没有副作用,因为我看到了这个回答;我想我在这个问题上非常清楚,我明白编译器不能自动确定。我问的是是否有一个适当的框架,即向编译器提供一个提示,就像您在决定内联/不内联方法时可以做的那样。编译器不能基于一些任意假设进行优化编译器实际上可以做到这一点。数据库优化器就是这样做的。对于常量真/假表达式,编译器可以对其进行优化,甚至完全删除整个if语句。var标志=假;if标志&&SomethingElse{…}@zerkms:SomethingElse仍然可以返回true,因此如果不能删除if,可以使用&&。但这不是一个武断的假设,这只是计算一个常量。如果编译器要洗牌逻辑运算符的操作数,它必须考虑到副作用,因为执行顺序决定哪些操作数得到计算,哪些不得到计算。@knittl:我同意。我的观点是编译器可能会基于短路进行一些很好的优化。语句ifbool_a | | bool_b | | bool_c对于bool_a、bool_b和bool_c的顺序没有区别。我想问的是,是否有一种内置方法可以使一个无副作用的方法以这种方式运行。您可以添加属性来告诉编译器内联或不内联您的方法。。。我不认为我的问题有什么不同。内联并没有实质性地影响程序的语义。更改短路操作器的评估顺序不起作用。编译器应仅执行与程序员编写的代码兼容的优化。给定布尔值bool_a和bool_b,ifbool_a | | | bool_b和ifbool_b | bool_a是否在功能上不等效?通常情况下,如果它们都是预先计算的布尔变量或常量,在这种情况下,重新安排它们是没有好处的。例如,bool_b可能是一个可能有副作用的属性,或者抛出一个exc
如果bool_a不是真的,则为eption。在这种情况下,重新排列条件将导致程序行为不同。@Michael如果它们都是现有的预先计算的布尔变量,那么它们在功能上是等价的。如果其中一个是返回布尔值的方法,那么它们在功能上是不等价的。这并不能回答我的问题。我问解释是否可以让编译器知道在正确的情况下可以自由地将x | | y重新排列为y | | x,而不是在x为真时在ifx | | y中对y求值。@Michael答案是否定的。没有属性可以改变这种行为。该链接解释了| |的工作原理,但没有提到如何更改布尔运算的计算。我更新了答案。