IIf()和If之间的性能差异

102

在Visual Basic中,使用IIf函数是否比使用If语句具有更好的性能?

9个回答

144

我认为问题中提到的是VB中以下的If语句:

' Usage 1
Dim result = If(a > 5, "World", "Hello")
' Usage 2
Dim foo = If(result, "Alternative")

第一个是基本上与C#的三元条件运算符相同,而第二个是它的合并运算符(返回 result 除非它是 Nothing,此时返回 "Alternative")。因此,If 取代了 IIf,后者已经过时。

就像在 C# 中一样,VB 的条件 If 运算符也支持短路处理,因此您现在可以安全地编写以下代码,而使用 IIf 函数则不可能实现:

Dim len = If(text Is Nothing, 0, text.Length)

6
你没有回答关于性能的问题,也没有提到 IIf 的副作用。 - jor
2
@jor 我的回答的最后一段是关于副作用的。当其中一个选项已经过时时,性能并不重要。值得一提的是,本地运算符 IfIIf 函数要高效得多。 - Konrad Rudolph
2
@mmcrae 这是正确的,也是有意为之的:正如我所说,IIf已经过时了,因此讨论它没有太多意义。话虽如此,我的最后一段确实讨论了相关的差异。这就是你需要知道的全部内容。 - Konrad Rudolph
3
我很感激您想支持良好标准并确保新手不会学习到不好的实践方法,但有些人可能有完全合理的问题导致他们希望更好地了解区别...比如维护遗留代码、被困在使用它的某些其他工具中等等。而“这就是你需要知道的一切”听起来不像是一个致力于知识共享的网站所应持有的态度 ;) - Don Cheadle
1
@mmcrae 哦,我并不是想要轻视,我只是真的觉得 IIf 的内部实现非常无聊。它只是包含了一个传统的 If 语句,这意味着我回答中的最后一段代码不会运行。 - Konrad Rudolph
显示剩余2条评论

70

IIf() 同时运行真和假的代码。对于像数值赋值这样简单的事情来说,这并不是什么大问题。但对于需要任何处理的代码来说,你会浪费运行不匹配条件的周期,并可能导致副作用。

示例代码:

Module Module1
    Sub Main()
        Dim test As Boolean = False
        Dim result As String = IIf(test, Foo(), Bar())
    End Sub

    Public Function Foo() As String
        Console.WriteLine("Foo!")
        Return "Foo"
    End Function

    Public Function Bar() As String
        Console.WriteLine("Bar!")
        Return "Bar"
    End Function
End Module

输出:

Foo!
Bar!

13

另外,IIf语句还存在一个重大问题,即它会实际调用任何在参数[1]中的函数。因此,如果您遇到以下情况:

string results = IIf(Not oraData.IsDBNull(ndx), oraData.GetString(ndx), string.Empty)

实际上,该函数会抛出异常,这并不是大多数人第一次看到它时的想法。这也可能导致应用程序中一些非常难以修复的错误。

[1] IIf 函数 - http://msdn.microsoft.com/en-us/library/27ydhh0d(VS.71).aspx


这就是为什么如果要替换旧的IIF,我以前遇到过IIF的问题,但IF可以节省很多代码行。 - NiL

7

更好的做法是使用 If 而不是 IIf,以正确使用类型推断机制(Option Infer On)

在这个例子中,当我使用 If 时,Keywords 被识别为字符串:

Dim Keywords = If(String.IsNullOrEmpty(SelectedKeywords), "N/A", SelectedKeywords)

否则,它将被识别为一个对象:
Dim Keywords = IIf(String.IsNullOrEmpty(SelectedKeywords), "N/A", SelectedKeywords)

7

根据这位的说法,使用IIf可能需要比If/Then多6倍的时间。结果因人而异。


1
在我的经验计算中(10000000个循环),我评估了IIf的速度大约慢了12倍! - Phantômaxx

6
我认为If和IIf的主要区别在于:
  • If(test [boolean], statement1, statement2) 它意味着根据测试值,将执行语句1或语句2(只有一个语句会被执行)

  • Dim obj = IIF(test [boolean] , statement1, statement2) 它意味着两个语句都将执行,但根据测试值,其中之一将返回一个值给(obj)。

因此,如果其中一个语句引发异常,它将在(IIf)中抛出,但在(If)中仅在条件返回其值的情况下才会抛出异常。


6
此外,在这种情况下,易读性可能比性能更加重要。即使IIF更有效率,在目标受众中它也不如其他程序员容易理解(我认为如果您在使用Visual Basic,则希望其他程序员能够轻松阅读您的代码,这是VB的最大优点...但是在我看来,像IIF这样的概念会破坏这个优点)。
此外,《IIF是一个函数,而IF是语言语法的一部分》,这意味着,如果仅因为If语句可以直接简化为一小组操作码,而不必转到内存中的另一个空间执行该函数中找到的逻辑,那么它可能会更快...这只是微不足道的差异,但值得注意。

5

关于为什么IIf函数的执行速度可能会慢至6倍,维基百科如是说:

因为IIf是一个库函数,它总是需要函数调用的开销,而条件运算符更有可能产生内联代码。

实际上,IIf函数相当于C++/C#中的三元运算符,因此如果您愿意,它可以给您提供一些漂亮的1行if/else类型语句。您还可以给它一个要评估的函数。


1

这些函数是不同的!也许你只需要使用IF语句。

IIF会更慢,因为它会执行两个函数,还要执行标准的IF语句。

如果你想知道为什么有IIF函数,也许这就是解释:

Sub main()
    counter = 0
    bln = True
    s = iif(bln, f1, f2)
End Sub

Function f1 As String
    counter = counter + 1
    Return "YES"
End Function

Function f2 As String
    counter = counter + 1
    Return "NO"
End Function

因此,在此之后,计数器将为2,但s仅为“YES”。我知道这个计数器的东西是无用的,但有时候有些函数需要同时运行,无论IF是true还是false,只需从其中一个分配值给您的变量。


2
如果你需要同时运行它们,你应该显式地调用它们两个,然后执行标准的 If 语句。在这种方式中使用 IIf() 只会让阅读你代码的人感到困惑。 - Spivonious
我并不是想让这个评论听起来像是在批评,我只是想指出在这种情况下使用它并不是一个好的做法。 - Spivonious

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接