W jaki sposób kompilator VB.NET wybiera, które rozszerzenie przeciążenia ma być uruchamiane?

Masz ciekawą osobliwość - pomyślał, że ktoś może pomóc.

Wynikało to z zabawy z typami dopuszczającymi unieważnienie z tego pytania:

Jak sprawdzić, czy obiekt jest dopuszczalny?

Option Strict On

Module Test
  ' Call this overload 1
  <Extension()>
  Function IsNullable(obj As ValueType) As Boolean
    Return False
  End Function

  ' Call this overload 2
  <Extension()>
  Function IsNullable(Of T As {Structure})(obj As Nullable(Of T)) As Boolean
    Return True
  End Function

  Sub Test() 
    ' a is an integer!
    Dim a As Integer = 123

    ' calling IsNullable as an extension method calls overload 1 and returns false
    Dim result1 As Boolean = a.IsNullable()

    ' calling IsNullable as method calls overload 2 and returns true
    Dim result2 As Boolean = IsNullable(a)

    ' why? surely the compiler should treat both those calls as equivalent
  End Sub
End Module

Spodziewałbym się, że oba wywołania IsNullable będą traktowane przez kompilator tak samo, ale tak nie jest. Wywołanie metody rozszerzenia używa innego przeciążenia do normalnego wywołania metody, nawet jeśli argument „a” pozostaje niezmieniony.

Moje pytanie brzmi: dlaczego? Co sprawia, że ​​kompilator zmienia zdanie między dwoma połączeniami?

FTR: Używamy Visual Studio 2010, .NET Framework 4.

questionAnswers(2)

yourAnswerToTheQuestion