vb.net 嵌套 If Else 语句与 ElseIf 语句的性能差异

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18511699/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 14:51:25  来源:igfitidea点击:

Performance Differences of Nested If Else Statements vs. ElseIf Statements

.netvb.netif-statement

提问by Nicholas Post

A coworker and I have differing opinions on Ifstatements and their performance. My view is that If...ElseIfstatements should be used. His view is that he doesn't believein ElseIf, and writes everything with nested Ifstatements.

我和一位同事对If陈述及其表现有不同的看法。我的观点是If...ElseIf应该使用语句。他的观点是,他不相信ElseIf,并与嵌套写的一切If陈述。

Let's assume that a case statement cannot be used in this situation. What I am wondering is how efficiently code will be executed using nested If..Elsestatements versus using If...ElseIfstatements. I know that code readability is a factor, but that shouldn't' affect performance.

让我们假设在这种情况下不能使用 case 语句。我想知道的是,使用嵌套If..Else语句与 usingIf...ElseIf语句执行代码的效率如何。我知道代码可读性是一个因素,但这不应该影响性能。

Lets look at the following examples.

让我们看看下面的例子。

Using If Else:

使用如果其他:

If () then
    'Do something'
Else
    If () then
        'Do something'
    Else
        If () then
            'Do something'
        Else
            If () then
                'Do something'
            Else
                'Do something else'
            End If
        End If
    End If
End If

Using ElseIf:

使用 ElseIf:

If () then
    'Do something'
ElseIf () then
    'Do something'
ElseIf () then
    'Do something'
ElseIf () then
    'Do something'
Else
    'Do something else'
End If

I know this is a small scale example, but lets say blocks like this are used heavily throughout the application.

我知道这是一个小规模的例子,但可以说像这样的块在整个应用程序中被大量使用。

Are there any performance differences between the two code sections, or would they perform almost identically once the application is compiled?

两个代码段之间是否存在性能差异,或者在编译应用程序后它们的性能是否几乎相同?

####UPDATE#####

####更新#####

I created a program to test running through the functions x number of times.

我创建了一个程序来测试运行函数 x 次。

Public Class Form1

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    For i As Integer = 0 To 1000
        Run()
    Next
End Sub

Sub Run()

    Dim Time1Start As Integer = 0
    Dim Time1End As Integer = 0
    Dim Time2Start As Integer = 0
    Dim Time2End As Integer = 0

    Time2Start = CInt(DateTime.Now.ToString("fff"))
    runElse()
    Time2End = CInt(DateTime.Now.ToString("fff"))

    Time1Start = CInt(DateTime.Now.ToString("fff"))
    runElseIf()
    Time1End = CInt(DateTime.Now.ToString("fff"))

    TextBox1.Text += If(Time1End < Time1Start, Time1End + (1000 - Time1Start), Time1End - Time1Start) & vbTab & If(Time2End < Time2Start, Time2End + (1000 - Time2Start), Time2End - Time2Start) & vbCrLf
End Sub

Sub runElseIf()
    If sleep(10) Then
        'Do something'
    Else
        If sleep(10) Then
            'Do something'
        Else
            If sleep(10) Then
                'Do something'
            Else
                If sleep(10) Then
                    'Do something'
                Else
                    If sleep(10) Then
                        'Do something'
                    Else
                        If sleep(10) Then
                            'Do something'
                        Else
                            If sleep(10) Then
                                'Do something'
                            Else
                                If sleep(10) Then
                                    'Do something'
                                Else
                                    If sleep(10) Then
                                        'Do something'
                                    Else
                                        If sleep(10) Then
                                            'Do something'
                                        Else
                                            'Do something else'
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    End If
                End If
            End If
        End If
    End If
End Sub

Sub runElse()
    If sleep(10) Then
        'Do something'
    ElseIf sleep(10) Then
        'Do something'
    ElseIf sleep(10) Then
        'Do something'
    ElseIf sleep(10) Then
        'Do something'
    ElseIf sleep(10) Then
        'Do something'
    ElseIf sleep(10) Then
        'Do something'
    ElseIf sleep(10) Then
        'Do something'
    ElseIf sleep(10) Then
        'Do something'
    ElseIf sleep(10) Then
        'Do something'
    ElseIf sleep(10) Then
        'Do something'
    Else
        'Do something else'
    End If
End Sub

Function sleep(ByVal ms As Integer) As Integer
    System.Threading.Thread.Sleep(ms)
    Return False
End Function

End Class

I ran the program and here are my results:
500 Loops Average - ElseIf: 108.248ms If Else: 106.507ms
1000 Loops Average - ElseIf: 107.747ms If Else: 107.451ms (Else If running first)
1000 Loops Average - ElseIf: 107.683ms If Else: 107.076ms (ElseIf running first)

我运行了程序,这是我的结果:
500 次循环平均 - ElseIf:108.248 毫秒如果其他:106.507 毫秒
1000 次循环平均值 - ElseIf:107.747 毫秒如果其他:107.451 毫秒(否则如果首先运行)
1000 次循环平均值:1307 毫秒。 If Else: 107.076ms (ElseIf 先运行)

Perhaps with a larger data set the numbers would change, but out of those 3 trials it actually appears that the If Elseis outperforming the ElseIfstatements.

也许使用更大的数据集,数字会发生变化,但在这 3 次试验中,实际上似乎If Else表现优于ElseIf陈述。

回答by the_lotus

I've decompiled the two and it seem to be generating the same code (using ildasm). This is a very simple If statment, might get different result for different If. I would suggest you do the same with your code and see.

我已经反编译了两者,它似乎生成了相同的代码(使用 ildasm)。这是一个非常简单的 If 语句,不同的 If 可能得到不同的结果。我建议你对你的代码做同样的事情,然后看看。

Module Module1

    Sub Main()

        Dim a As Integer
        Dim i As Integer = 1

        If i = 1 Then
            a = 9
        ElseIf i = 2 Then
            a = 8
        ElseIf i = 3 Then
            a = 7
        Else
            a = 6
        End If

    End Sub

End Module



.method public static void  Main() cil managed
{
  .entrypoint
  .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 ) 
  // Code size       30 (0x1e)
  .maxstack  2
  .locals init ([0] int32 a,
           [1] int32 i)
  IL_0000:  ldc.i4.1
  IL_0001:  stloc.1
  IL_0002:  ldloc.1
  IL_0003:  ldc.i4.1
  IL_0004:  bne.un.s   IL_000b
  IL_0006:  ldc.i4.s   9
  IL_0008:  stloc.0
  IL_0009:  br.s       IL_001d
  IL_000b:  ldloc.1
  IL_000c:  ldc.i4.2
  IL_000d:  bne.un.s   IL_0013
  IL_000f:  ldc.i4.8
  IL_0010:  stloc.0
  IL_0011:  br.s       IL_001d
  IL_0013:  ldloc.1
  IL_0014:  ldc.i4.3
  IL_0015:  bne.un.s   IL_001b
  IL_0017:  ldc.i4.7
  IL_0018:  stloc.0
  IL_0019:  br.s       IL_001d
  IL_001b:  ldc.i4.6
  IL_001c:  stloc.0
  IL_001d:  ret
} // end of method Module1::Main

And the other one

而另一个

Module Module1

    Sub Main()

        Dim a As Integer
        Dim i As Integer = 1

        If i = 1 Then
            a = 9
        Else
            If i = 2 Then
                a = 8
            Else
                If i = 3 Then
                    a = 7
                Else
                    a = 6
                End If
            End If
        End If

    End Sub

End Module

.method public static void  Main() cil managed
{
  .entrypoint
  .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 ) 
  // Code size       30 (0x1e)
  .maxstack  2
  .locals init ([0] int32 a,
           [1] int32 i)
  IL_0000:  ldc.i4.1
  IL_0001:  stloc.1
  IL_0002:  ldloc.1
  IL_0003:  ldc.i4.1
  IL_0004:  bne.un.s   IL_000b
  IL_0006:  ldc.i4.s   9
  IL_0008:  stloc.0
  IL_0009:  br.s       IL_001d
  IL_000b:  ldloc.1
  IL_000c:  ldc.i4.2
  IL_000d:  bne.un.s   IL_0013
  IL_000f:  ldc.i4.8
  IL_0010:  stloc.0
  IL_0011:  br.s       IL_001d
  IL_0013:  ldloc.1
  IL_0014:  ldc.i4.3
  IL_0015:  bne.un.s   IL_001b
  IL_0017:  ldc.i4.7
  IL_0018:  stloc.0
  IL_0019:  br.s       IL_001d
  IL_001b:  ldc.i4.6
  IL_001c:  stloc.0
  IL_001d:  ret
} // end of method Module1::Main

I would suggest to use the one that is easier to read.

我建议使用更容易阅读的那个。

回答by STW

You're worrying about the wrong things!!!

你担心的事情不对!!!

The code you write isn't the code that is executed. The compiler will modify the structure of your code for optimization, and it does very well with things such as this. That said, even if it didn't perform optimizations the speed difference wouldn't matter.

您编写的代码不是执行的代码。编译器将修改您的代码结构以进行优化,它在诸如此类的事情上做得很好。也就是说,即使它没有执行优化,速度差异也无关紧要。

Don't worry about "is it as fast as it can be?" Instead worry about "is it fast enough, and as maintainable (readable) as it can be?".

不用担心“它是否尽可能快?” 而是担心“它是否足够快,并且尽可能地可维护(可读)?”。

Compilers and processors are very good at understanding logic structures, but meatbags (people) aren't. Whenever you write code you should try to make sure that it's as approachable and readable as possible. If you find that it's unacceptible slow then you can begin sacrificing readability for performance--but doing so out of paranoia is called "premature optimization", and it's a great way to make code that will be unmaintainable (and eventually spawn bugs).

编译器和处理器非常擅长理解逻辑结构,但肉袋(人)不是。每当你编写代码时,你应该尽量确保它尽可能平易近人和可读。如果您发现它的速度慢得令人无法接受,那么您可以开始牺牲可读性以换取性能——但出于偏执而这样做被称为“过早优化”,这是使代码无法维护(并最终产生错误)的好方法。

With that said, here's some guidelines:

话虽如此,这里有一些指导方针:

  • Methods with many ifs/elses are a code-smell (they have a high "cyclomatic complexity". It indicates that a single method does many this, which makes it hard to read, maintain, test, and alter. Decompose your method into many smaller methods. You may still end up with a relatively large "control" method, which determines what to do--but delegate the task of actually doing it to other methods.

  • Reduce nesting as much as possible.

    If there are cases that result in a simple returnor exit then try to check them early in the sequence: (e.g. if (something) { return; }).

  • Group related checks together, and try to refactor them to their own method

  • Cover it all extensively in tests

  • 有很多 ifs/else 的方法是一种代码味道(它们具有很高的“圈复杂度”。这表明单个方法做了很多这样的事情,这使得阅读、维护、测试和更改变得困难。将你的方法分解成许多较小的方法。您最终可能仍会得到一个相对较大的“控制”方法,它决定了要做什么——但将实际执行的任务委托给其他方法。

  • 尽可能减少嵌套。

    如果存在导致简单return或退出的情况,则尝试在序列的早期检查它们:(例如if (something) { return; })。

  • 将相关的检查组合在一起,并尝试将它们重构为自己的方法

  • 在测试中广泛涵盖所有内容

回答by plalx

Well, I believe that it would all depend on the conditions you are checking.

好吧,我相信这完全取决于您检查的条件。

For example (pseudo-code):

例如(伪代码):

if (A && B) {
} elseif (A && C) {
} elseif (A && D) {
}

In this example, there's a common condition shared between all ifstatements, which means that re-writing to the following is probablymore efficient:

在此示例中,所有if语句之间共享一个共同条件,这意味着重写以下内容可能更有效:

if (A) {
    if (B) {
    } elseif (C) {
    } elseif (D) {
    }
}

However, if you cache the result of the Acondition. The performance gains would probably minimal. Perhaps there are even optimizations performed by the compiler, so you would have to run a performance test to make sure there's even a difference in execution time.

但是,如果您缓存A条件的结果。性能提升可能很小。也许编译器甚至会执行优化,因此您必须运行性能测试以确保执行时间存在差异。

More importantly, unless you are writing some performance-critical code, always try to write code by focusing on readability. There's almost always an efficient way of flattening conditionnal statements without hurting efficiency anyway.

更重要的是,除非您正在编写一些对性能至关重要的代码,否则请始终尝试通过关注可读性来编写代码。几乎总是有一种有效的方法可以在不损害效率的情况下展平条件语句。

回答by dbasnett

From a performance perspective there is no meaningful difference. For me the readability of the ElseIf is clearly better.

从性能的角度来看,没有有意义的区别。对我来说,ElseIf 的可读性显然更好。

Private Sub xelseif(tries As Integer)
    Dim foo As Integer
    For x As Integer = 1 To tries
        For y As Integer = 1 To 5 Step 4
            If y = 1 Then
                foo = y
            ElseIf y = 2 Then
            ElseIf y = 3 Then
            ElseIf y = 4 Then
            ElseIf y = 5 Then
                foo = y
            End If
        Next
    Next
End Sub

Private Sub xelse(tries As Integer)
    Dim foo As Integer
    For x As Integer = 1 To tries
        For y As Integer = 1 To 5 Step 4
            If y = 1 Then
                foo = y
            Else
                If y = 2 Then
                Else
                    If y = 3 Then
                    Else
                        If y = 4 Then
                        Else
                            If y = 5 Then
                                foo = y
                            End If
                        End If
                    End If
                End If
            End If
        Next
    Next
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim stpw As New Stopwatch
    Dim tries As Integer = 1500000

    xelse(10)
    stpw.Restart()
    xelse(tries)
    stpw.Stop()
    Debug.WriteLine(stpw.ElapsedMilliseconds)

    xelseif(10)
    stpw.Restart()
    xelseif(tries)
    stpw.Stop()
    Debug.WriteLine(stpw.ElapsedMilliseconds)
End Sub

回答by Sasidharan

It depends on your code.

这取决于您的代码。

The if statement is only accessed when a condition is met, otherwise it is ignored. the if elseif else block is the same but it is testing for many conditions and depending on which one is met a different action might have to be performed in order to get the results u want.

if 语句仅在满足条件时访问,否则将被忽略。if elseif else 块是相同的,但它正在测试许多条件,并且根据满足哪个条件,可能必须执行不同的操作才能获得您想要的结果。

My opinion is "It depends upon cases".

我的意见是“视情况而定”。

If you want to execute everything in your code,then use elseif..

如果要执行代码中的所有内容,请使用 elseif..

if you want to ignore something use if..

如果您想忽略某些内容,请使用 if..

回答by No Idea For Name

i always prefer switch case when i have that many ifelseif, but i know it's always possible. in that case the ElseIfalways looks better, and is implemented in the background with else if, so it's should be the same performances.

当我有那么多的时候ifelseif,我总是更喜欢 switch case ,但我知道这总是可能的。在这种情况下,它ElseIf总是看起来更好,并且在后台使用 实现else if,所以它应该是相同的性能。

but! for a lot of people, including some of my co-workers and bosses, it is not readable because the read it as ififif. i know it's crazy but it's some psychology thing i think.... so i understand where your coworker coming from

但!对于很多人来说,包括我的一些同事和老板,它不可读,因为它读作ififif. 我知道这很疯狂,但我认为这是一些心理学问题....所以我明白你的同事来自哪里

回答by James Lawruk

I ran a quick test and found that ElseIf runs slightly faster than Nested If. See the code below.

我进行了一个快速测试,发现ElseIf 的运行速度比 Nested If 稍快。请参阅下面的代码。

Imports System.Diagnostics
Module Module1

    Sub Main()
        Dim sw As New Stopwatch()
        Dim nestedTotal As Integer
        sw.Start()
        For i = 1 To 100000
            Nested()
        Next
        sw.Stop()
        nestedTotal = sw.ElapsedMilliseconds

        sw.Reset()

        Dim elsesTotal As Integer
        sw.Start()
        For i = 1 To 100000
            Elses()
        Next
        sw.Stop()
        elsesTotal = sw.ElapsedMilliseconds
        Console.WriteLine("Nested If:" & nestedTotal)
        Console.WriteLine("ElseIf:" & elsesTotal)
        Console.Read()
    End Sub

    Sub Nested()
        Dim num As Integer = GetNum()
        If num = 1 Then
            DoSomething()
        Else
            If num = 2 Then
                DoSomething()
            Else
                If num = 3 Then
                    DoSomething()
                Else
                    If num = 4 Then
                        DoSomething()
                    Else
                        DoSomething()
                    End If
                End If
            End If
        End If
    End Sub

    Sub DoSomething()
        Dim j As Integer
        For i = 1 To 1000
            j = i + j
        Next
    End Sub

    Sub Elses()
        Dim num As Integer = GetNum()
        If num = 1 Then
            DoSomething()
        ElseIf num = 2 Then
            DoSomething()
        ElseIf num = 3 Then
            DoSomething()
        ElseIf num = 4 Then
            DoSomething()
        Else
            DoSomething()
        End If
    End Sub

    Function GetNum()
        Dim Generator As System.Random = New System.Random()
        Return Generator.Next(1, 5)
    End Function
End Module