“If(..||..)"中发生了什么?和“If(...&&...)"内部构造? [英] What is happening in an "If(..||..)" and "If(...&&...)" construct internally?
问题描述
我只是想知道在if OR"和if AND"内部会发生什么.我有一种感觉,它只是语法糖来使用&&
和 ||
以及内部所有 case 都构建为单个 if 语句.
I was just wondering what happens inside of an "if OR" and "if AND". I have a feeling that it's just syntactic sugar to use &&
and ||
and internally all cases are build as single if statements.
紧凑形式||:
if(a || b || c)
{
DoSomething();
}
潜在的内部形式:
if(a)
{
DoSomething();
}
else if(b)
{
DoSomething();
}
else if(c)
{
DoSomething();
}
<小时>
紧凑形式&&:
Compact form &&:
if(a && b && c)
{
DoSomething();
}
潜在的内部形式:
if(a)
{
if(b)
{
if(c)
{
DoSomething();
}
}
}
这两个例子的性能有什么不同吗?
Is there any difference in the performance of these two examples?
*将 else 添加到 ||案例
* Added the else to the || case
推荐答案
首先,||
和 &&
是 短路.这意味着在:
First of all, ||
and &&
are short-circuit. Which mean that in:
if(a || b || c)
DoSomething();
如果 a
为真,b
和 c
将不会被评估.
if a
is true, b
and c
will not be evaluated.
其次,您对 ||
的实现是错误的:
Secondly, your implementation of the ||
is false:
if(a)
DoSomething();
if(b)
DoSomething();
if(c)
DoSomething();
DoSomething()
将被调用最多 3 次.
应该是:
if(a)
DoSomething();
else if(b)
DoSomething();
else if(c)
DoSomething();
最后,如果您希望性能在您的条件下优先选择更短的通话:
To finish, if you want performance prefer shorter call first in your conditions:
if(aShortFunctionToExecute() || aVeryVeryLongFunctionToExecute())
DoSomething();
会比
if(aVeryVeryLongFunctionToExecute() || aShortFunctionToExecute())
DoSomething();
因为懒惰评估
如果你反汇编以下代码:
If you disassemble the code of:
private static void Main()
{
if (a() && b() && c())
{
Console.WriteLine("DoSomething");
}
}
bool a(){
return true;
}
bool b(){
return 3 % 2 == 1;
}
bool c(){
return (3 % 2) / 1 == 1;
}
你会得到:
if (a() && b() && c())
00000022 call FFFFFFFFFFEE8D90
00000027 mov byte ptr [rbp+20h],al
0000002a movzx eax,byte ptr [rbp+20h]
0000002e test eax,eax
00000030 je 000000000000005A
00000032 call FFFFFFFFFFEE8D98
00000037 mov byte ptr [rbp+21h],al
0000003a movzx eax,byte ptr [rbp+21h]
0000003e test eax,eax
00000040 je 000000000000005A
00000042 call FFFFFFFFFFEE8DA0
00000047 mov byte ptr [rbp+22h],al
0000004a movzx ecx,byte ptr [rbp+22h]
0000004e xor eax,eax
00000050 test ecx,ecx
00000052 sete al
00000055 mov dword ptr [rbp+24h],eax
00000058 jmp 0000000000000062
0000005a nop
0000005b mov dword ptr [rbp+24h],1
00000062 nop
00000063 movzx eax,byte ptr [rbp+24h]
00000067 mov byte ptr [rbp+2Fh],al
0000006a movzx eax,byte ptr [rbp+2Fh]
0000006e test eax,eax
00000070 jne 0000000000000087
{
00000072 nop
Console.WriteLine("DoSomething");
00000073 mov rcx,12603398h
0000007d mov rcx,qword ptr [rcx]
00000080 call 00000000577A82A0
00000085 nop
}
和代码:
private static void Main()
{
if (a())
if(b())
if(c())
Console.WriteLine("DoSomething");
}
static bool a(){
return true;
}
static bool b(){
return 3 % 2 == 1;
}
static bool c(){
return (3 % 2) / 1 == 1;
}
你会得到:
if (a())
00000022 call FFFFFFFFFFEE8D90
00000027 mov byte ptr [rbp+20h],al
0000002a movzx ecx,byte ptr [rbp+20h]
0000002e xor eax,eax
00000030 test ecx,ecx
00000032 sete al
00000035 mov dword ptr [rbp+24h],eax
00000038 movzx eax,byte ptr [rbp+24h]
0000003c mov byte ptr [rbp+3Fh],al
0000003f movzx eax,byte ptr [rbp+3Fh]
00000043 test eax,eax
00000045 jne 00000000000000A4
if(b())
00000047 call FFFFFFFFFFEE8D98
0000004c mov byte ptr [rbp+28h],al
0000004f movzx ecx,byte ptr [rbp+28h]
00000053 xor eax,eax
00000055 test ecx,ecx
00000057 sete al
0000005a mov dword ptr [rbp+2Ch],eax
0000005d movzx eax,byte ptr [rbp+2Ch]
00000061 mov byte ptr [rbp+3Fh],al
00000064 movzx eax,byte ptr [rbp+3Fh]
00000068 test eax,eax
0000006a jne 00000000000000A4
if(c())
0000006c call FFFFFFFFFFEE8DA0
00000071 mov byte ptr [rbp+30h],al
00000074 movzx ecx,byte ptr [rbp+30h]
00000078 xor eax,eax
0000007a test ecx,ecx
0000007c sete al
0000007f mov dword ptr [rbp+34h],eax
00000082 movzx eax,byte ptr [rbp+34h]
00000086 mov byte ptr [rbp+3Fh],al
00000089 movzx eax,byte ptr [rbp+3Fh]
0000008d test eax,eax
0000008f jne 00000000000000A4
Console.WriteLine("DoSomething");
00000091 mov rcx,125D3398h
0000009b mov rcx,qword ptr [rcx]
0000009e call 00000000577B82A0
000000a3 nop
稍长一点:它需要 40 条指令而不是 31 条指令.
Which is a bit longer: it takes 40 instructions instead of 31.
正如 thanosqr 所指出的,性能还取决于您的条件为真的概率.以他的例子为例:
As pointed out by thanosqr, the performance also depend of the probability for your condition to be true. To take his example:
如果 a
在 99% 的时间内失败并且需要 1 秒才能运行,如果 b
99% 的成功率并需要 10 秒才能运行,超过 100 次尝试你会更快地将 b
放在首位:
If a
fails 99% of the time and take 1 sec to run and if b
succeed 99% of the time and take 10 sec to run, over 100 tries you'll be faster putting b
first:
if(b || a) => 10s 99% ==> 100 runs will take 99*10+11 = 1001s
if(b || a) => 11s 1%
if(a || b) => 11s 99% ==> 100 runs will take 99*11+1 = 1090s
if(a || b) => 1s 1%
另外,我建议你阅读为什么处理排序数组比处理未排序数组更快? "这很有趣!
Also, I suggest you this reading " Why is it faster to process a sorted array than an unsorted array? " which is quite interesting!
这篇关于“If(..||..)"中发生了什么?和“If(...&&...)"内部构造?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!