我有一个巨大的DataTable,我需要遍历每一行并验证一个特定的值。
哪种方法给我更多的性能,IF ELSE或SELECT CASE的结构? (我专注于为我提供最佳性能的方法)
IF ELSE(方法#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
选择案例(方法#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
答案 0 :(得分:5)
没有区别,两种代码样式都生成完全相同的IL。通过在已编译的程序集上运行ildasm.exe工具可以看到的东西。
通常,VB.NET编译器 会努力优化Select语句。当它使用简单的值类型作为选择器和普通的Case语句时,这将起作用。生成的代码将使用专用的IL指令Opcodes.Switch。将编译为使用查找表的机器代码。很快。
当您使用字符串表达式作为选择器时,这不起作用。为那个制作查找表需要相当于委托的字典。这太有影响了,编译器不能做任何事情,只能将每个case语句转换为If语句的等价物。但是,您可以通过在代码中创建此Dictionary来轻松地自行优化,因为字典键和值只是简单的字符串。虽然值得一试,但是你没有足够的情况并且字符串太短而不能使这种情况发生重大回报。它当然可以压缩你的代码。
答案 1 :(得分:4)
在过去的几天里,我花了很多时间研究同样的问题,并且找到了一种比其他方法快得多的方法。我也发现在字符串变量上使用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
更改它以打开一个简单的布尔值,并使用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
通过以这种方式接近它,我获得了显着的改进,在一种情况下,将我的代码从100,000秒迭代循环中的1.3秒减少到0.5秒。如果这是一个经常被称为时间关键的代码段,那可能会产生很大的不同。
正如下面的评论所指出的,这会对字符串执行“序数”比较,如果使用非英语语言环境,则可能不会导致预期的行为(请参阅示例的注释)。
亚当。
答案 2 :(得分:4)
好的...很久以前这篇文章,但现在我正在搜索相同的问题,我可以为此添加新的优化。现在我选择使用选择案例,以便更具可读性。另一方面,当“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
即使你想使用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
我希望这对更多的人有帮助;)
答案 3 :(得分:2)
如果您确实发现这是性能瓶颈,您可以尝试按如下方式修改If..Then子句,只访问索引器一次:
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
话虽如此,我怀疑这些都是过度优化的情况。编译器应该在这里做到最好。如果从长选择案例中检查IL,您可能会发现它使用带有“goto”的封面下的一串If..then子句来转义其余的子句。这里你最好的选择是获得最易维护的代码,因为你可能获得的性能优势将被你在...和select case之间看到的最小提升所抵消。