VB.NET如何提供最佳性能"选择案例"或IF ... ELSEIF ... ELSE ... END IF

MiB*_*Bol 6 vb.net performance if-statement cycle switch-statement

我有一个巨大的DataTable,我需要遍历每一行并验证一个特定的值.

哪种方法给我更多的性能,IF ELSE或SELECT CASE的结构?(我专注于为我提供最佳性能的方法)

如果是(方法#1)

For Each vRow In vDTtemp.Rows
    If vRow("Item") = "Time" Then
        vRow("Result") = "000"
    ElseIf vRow("Item") = "DateTime" Then
        vRow("Result") = "001"
    ElseIf vRow("Item") = "String" Then
        vRow("Result") = "002"
    Else
        vRow("Result") = "N/A"
    End If
Next
Run Code Online (Sandbox Code Playgroud)

选择案例(方法#2)

For Each vRow In vDTtemp.Rows
    Select Case vRow("Item")
        Case "Time"
            vRow("Result") = "000"
        Case "DateTime"
            vRow("Result") = "001"
        Case "String"
            vRow("Result") = "002"
        Case Else
            vRow("Result") = "N/A"
    End Select
Next
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 6

它没有区别,两种代码样式都生成完全相同的IL.通过在编译的程序集上运行ildasm.exe工具可以看到的东西.

通常,VB.NET编译器努力优化Select语句.当它使用简单的值类型作为选择器和普通的Case语句时,这将起作用.生成的代码将使用专用的IL指令Opcodes.Switch.将编译为使用查找表的机器代码.非常快.

但是,当您使用字符串表达式作为选择器时,这不起作用.为那个制作查找表需要相当于委托的字典.这太有影响了,编译器不能做任何事情,只能将每个case语句转换为If语句的等价物.但是,您可以通过在代码中创建此Dictionary来轻松地自行优化,因为字典键和值只是简单的字符串.虽然值得一试,但是你没有足够的情况并且字符串太短而不能使这种情况发生重大回报.它当然可以压缩你的代码.


Ada*_*wes 5

在过去的几天里,我已经花了很多时间来研究这个问题,并且发现一种方法要比其他方法快得多。我也发现在字符串变量上使用Select Case等效于一系列的If / Else If语句,并且它们都令人失望地慢。

但是,以下技术效果很好,将时间减少了50%以上。代替原始代码:

For Each vRow In vDTtemp.Rows
    Select Case vRow("Item")
        Case "Time"
            vRow("Result") = "000"
        Case "DateTime"
            vRow("Result") = "001"
        Case "String"
            vRow("Result") = "002"
        Case Else
            vRow("Result") = "N/A"
    End Select
Next
Run Code Online (Sandbox Code Playgroud)

更改它以打开简单的布尔值,并使用String.Equals方法,如下所示:

For Each vRow In vDTtemp.Rows
    'Read out the row value so we only need to access the datarow once
    rowValue = vRow("Item")
    'Which of these statements is true?
    Select Case True
        Case rowValue.Equals("Time")
            vRow("Result") = "000"
        Case rowValue.Equals("DateTime")
            vRow("Result") = "001"
        Case rowValue.Equals("String")
            vRow("Result") = "002"
        Case Else
            vRow("Result") = "N/A"
    End Select
Next
Run Code Online (Sandbox Code Playgroud)

通过这种方式实现了我的重大改进,在一种情况下,我的代码从100,000次迭代循环中的1.3秒减少到0.5秒。如果这是在经常被称为时间关键的代码部分中,那将有很大的不同。

但是,如下面的注释中所指出的那样,这将对字符串执行“序数”比较,如果使用的是非英语语言环境,则可能不会导致预期的行为(请参见示例注释)。

亚当。

  • 这以危险的方式与原始代码不兼容,您确实需要在答案中提出警告。加速很容易解释,String.Equals()使用StringComparison.Ordinal。比较字符串的最快方法,但是在各种语言中都有相当麻烦的语义。一个德国用户不会理解为什么ss与ß不匹配。土耳其语我臭名昭著。Etcetera。从坚决的Select Case语句中删除此错误的正常方法是`Option Compare Binary`。 (2认同)

小智 5

好吧……这篇文章很久以前了,但现在我正在搜索同样的问题,我可以为此添加新的优化。现在我选择使用 select 案例,以提高可读性。另一方面,当“Dim”在 for-next 循环中时,性能会下降很多。

     For Each vRow In vDTtemp.Rows
------->  Dim rowItem = vRow("Item")
        If rowItem = "Time" Then
            vRow("Result") = "000"
        ElseIf rowItem = "DateTime" Then
            vRow("Result") = "001"
        ElseIf rowItem = "String" Then
            vRow("Result") = "002"
        Else
            vRow("Result") = "N/A"
        End If
    Next
Run Code Online (Sandbox Code Playgroud)

即使您想使用 if-then 结构,当 dim 位于 oitside 时也会快得多:

------->     Dim rowItem as string
             For Each vRow In vDTtemp.Rows
------->            rowitem= vRow("Item")
                If rowItem = "Time" Then
                    vRow("Result") = "000"
                ElseIf rowItem = "DateTime" Then
                    vRow("Result") = "001"
                ElseIf rowItem = "String" Then
                    vRow("Result") = "002"
                Else
                    vRow("Result") = "N/A"
                End If
            Next
Run Code Online (Sandbox Code Playgroud)

我希望这对更多人有帮助;)