我只是想知道在“如果是OR ”和“如果是AND ”内部会发生什么。我觉得使用&&||只是syntactic sugar,内部所有情况都作为单个if语句构建。

紧凑形式||:

if(a || b || c)
{
    DoSomething();
}

潜在的内部形式:
if(a)
{
    DoSomething();
}
else if(b)
{
    DoSomething();
}
else if(c)
{
    DoSomething();
}

紧凑形式&&:
if(a && b && c)
{
    DoSomething();
}

潜在的内部形式:
if(a)
{
    if(b)
    {
        if(c)
        {
            DoSomething();
        }
    }
}

这两个示例的性能是否有所不同?

*编辑:将else添加到||案子

最佳答案

首先,||&&short-circuit。这意味着:

if(a || b || c)
    DoSomething();

如果a为true,则不评估bc

其次,您对||的实现是错误的:
if(a)
    DoSomething();
if(b)
    DoSomething();
if(c)
    DoSomething();
DoSomething()最多称为 3次

它应该是:
if(a)
    DoSomething();
else if(b)
    DoSomething();
else if(c)
    DoSomething();

最后,如果您想提高性能,则在您的情况下首选短打:
if(aShortFunctionToExecute() || aVeryVeryLongFunctionToExecute())
     DoSomething();

会比
if(aVeryVeryLongFunctionToExecute() || aShortFunctionToExecute())
     DoSomething();

因为lazy-evaluation

如果您反汇编以下代码:
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条指令。

thanosqr所指出的,性能还取决于您的条件为真的概率。以他为例:

如果a在99%的时间内失败,则需要1秒才能运行,并且b 成功99%的时间并需要10秒才能运行,超过100次尝试会更快地将b放在首位:
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%

另外,我建议您阅读“Why is it faster to process a sorted array than an unsorted array?”,这很有趣!

关于c# - 内部的 “If(..||..)”和 “If(…&&…)”构造中发生了什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29141368/

10-13 06:31