문제

Taking the following code in VB2012, I expect foo to be initialized to Nothing:

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

However, it throws an ArgumentException:

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

I don't quite understand this error message, but the situation gets outright scary if I change the type of foo to Func(Of Integer, Integer). In that case the code runs with no errors, but foo gets to be a mysterious lambda expression, which throws a NullReferenceException when called.

If I use the traditional If statement instead of the If function, the code works as expected.

Could someone explain this behaviour to me?

도움이 되었습니까?

해결책

Looks like IIf works just fine:

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

But I have to say, I have no idea why.

Update

OK, I think I have a reason. Compiler optimizes your code to following:

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

and that's why you get an exception.

Even when you don't use True as condition, and try to use variable

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

it's being transformed into:

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)

which will throw exception anyway.

다른 팁

Looks like a bug in compiler, because this code is equivalent, but it works as expected:

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

I was also able to reproduce your mysterious lambda expression using this code:

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

Which is logically equivalent to your statement (Nothing should get implicitly converted to 0).

This is weird - if compiler wants to optimize something, I would expect it to optimize in the same way as it would do for below statement. However, the below statement behaves as expected:

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

Because True is always True, both this statement and yours should result in the same code.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top