If()函数和VB中的委托

时间:2014-02-01 21:56:26

标签: .net vb.net delegates conditional-operator

在VB2012中使用以下代码,我希望将foo初始化为Nothing:

 Dim foo As Func(Of Integer) = If(True, Nothing, Function() 0)

但是,它会抛出ArgumentException:

Delegate to an instance method cannot have null 'this'.

我不太明白这个错误消息,但是如果我将foo的类型更改为Func(Of Integer,Integer),情况就会变得非常可怕。在这种情况下,代码运行时没有错误,但是foo变成了一个神秘的lambda表达式,在调用时会抛出NullReferenceException。

如果我使用传统的If语句而不是If函数,代码将按预期工作。

有人可以向我解释这种行为吗?

2 个答案:

答案 0 :(得分:1)

看起来IIf效果很好:

Dim foo As Func(Of Integer) = IIf(True, Nothing, Function() 0)

但我不得不说,我不知道为什么。

更新

好的,我想我有理由。编译器将您的代码优化为以下内容:

Dim foo As Func(Of Integer) = New Func(Of Integer)(Nothing.Invoke)

这就是你得到例外的原因。

即使您不使用True作为条件,也尝试使用变量

Dim t = Integer.Parse(Console.ReadLine()) < 10
Dim foo As Func(Of Integer) = If(t, Nothing, Function() 0)

它正在变成:

Dim foo As Func(Of Integer) = New Func(Of Integer)((If((Integer.Parse(Console.ReadLine()) < 10), Nothing, New VB$AnonymousDelegate_0(Of Integer)(Nothing, ldftn(_Lambda$__1)))).Invoke)

无论如何都会抛出异常。

答案 1 :(得分:1)

看起来像编译器中的错误,因为此代码是等效的,但它按预期工作:

Dim f As Func(Of Integer) = Function() 0
Dim foo As Func(Of Integer) = If(True, Nothing, f)

我还能够使用以下代码重现您的神秘的lambda表达式

Dim foo As Func(Of Integer) = If(True, Nothing, Function() Nothing)

在逻辑上等同于您的陈述(Nothing应隐式转换为0)。

这很奇怪 - 如果编译器想要优化某些东西,我希望它能够像下面的语句一样进行优化。但是,以下语句的行为符合预期:

Dim foo As Func(Of Integer) = If(True, Nothing, Nothing)

由于True始终为True,因此此语句和您的语句都应生成相同的代码。