7

興味深い奇妙な点がありました - 誰かが助けてくれるかもしれないと思いました。

これは、この質問からの null 許容型のいくつかの楽しみから生まれました。

オブジェクトがnull可能かどうかを確認する方法は?

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

IsNullable への両方の呼び出しがコンパイラによって同じように処理されることを期待しますが、そうではありません。拡張メソッド呼び出しは、引数 "a" が変更されていなくても、通常のメソッド呼び出しとは異なるオーバーロードを使用します。

私の質問はなぜですか?コンパイラが 2 つの呼び出しの間で考えを変える理由は何ですか?

FTR: Visual Studio 2010、.NET Framework 4 を使用しています。

4

2 に答える 2

2

オーバーロード 2 は、明示的に定義された Nullable(of T) の拡張機能としてのみ機能します。例えば:

    Dim y As New Nullable(Of Integer)
    y.IsNullable()

これは、拡張メソッドが型 (または基本型) を拡張するためです。この場合は Nullable(of T) です。a.IsNullable() を呼び出すと、オーバーロード 2 が呼び出されることはありません。これは簡単に理解できる部分です。つまり、実際の問題は、標準のオーバーロードされたメソッド呼び出しとしてオーバーロード 1 の代わりにオーバーロード 2 が呼び出される理由です。

CLR は、「Better Conversion」チェックを実行することで、使用するオーバーロードを決定します。このチェックでは、渡された値を、オーバーロードされたメソッドで定義されたパラメーターの型に暗黙的に変換し、ルールのチェックリストをたどります。使用する最適な方法を決定します。

MSDN のより良い変換の記事から:

S が T1 の場合、C1 の方が優れた変換です。

S が T2 の場合、C2 の方が優れた変換です。

このコードを Visual Studio に入れると、オーバーロード 2 の方が適切な変換であることがわかります。これは、整数 a (S) が暗黙的に変換された (整数の) Nullable バージョンの a (T2) であるためです。

    ' a is an integer! 
    Dim a As Integer = 123

    Dim objValueType As ValueType = 123 'Or CType(a, ValueType)
    Dim objNullable As Nullable(Of Integer) = 123 'Or CType(a, Nullable(Of Integer))

    'Oh No, a compiler error for implicit conversion done for overload 1!
    Dim bolValueTypeConversionIsBetter As Boolean = (objValueType = a)

    'No error as long as Option Strict is off and it will equal True.
    Dim bolNullableConversionIsBetter As Boolean = (objNullable = a)
于 2012-09-07T20:45:52.547 に答える