在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函数,代码将按预期工作。
有人可以向我解释这种行为吗?
答案 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
,因此此语句和您的语句都应生成相同的代码。