Got an interesting oddity – thought someone might be able to help.
This came out of some fun with nullable types from this question:
How to check if an object is nullable?
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
I would expect that both calls to IsNullable would be treated the same by the compiler, but that is not the case. The extension method call uses a different overload to the normal method call even though the argument “a” is unchanged.
My question is why? What makes the compiler change its mind between the two calls?
FTR: We are using Visual Studio 2010, .NET Framework 4.
I think this is a bug, or at least a VB.NET “feature”. (I’m just not sure which of VB.NET or C# is wrong.)
I have tried in LINQPad 4 (because that’s what I’ve got on the machine I’m using) and for C# I got
Falsefor both results, for every value type and enum except forNullabletypes, of course.Whereas for VB.NET I get the
FalseandTruefor all value types and enums, except forNullabletypes, andValueTypeand[Enum]which returnFalse,Falsebecause you can’t have aValueType?or[Enum]?. WithOption Strict Off,Objectcauses late binding, and fails at runtime to locate either overload, but the second result isFalsealso because you can’t haveObject?.For completeness,
Nullabletypes returnTrue,Truefor both languages as expected.The fact that C# is doing something different (assuming my test is correct) confirms the reference to the C# “Better Conversion” check is wrong (or being misread at least – in that C# is not doing what is being interpreted as why VB.NET is doing what it is doing).
However, I do agree that the issue is probably related to the implicit conversion to
Nullable(Of T)existing and somehow being a higher priority to the implicit conversion toValueType.Here’s my LINQPad 4 “Query” (C# Program):