Object の拡張メソッドは Objectで宣言できますが、 のように使用することはできませんobj.ExtMethod()
。これは仕様によるものです。一方、 のように任意の拡張メソッドを使用することもできますExtMethod(obj)
。Objectで宣言された拡張メソッドの呼び出しが、他の型で宣言された拡張メソッドと異なるのはなぜですか? この背後にあるロジックを探しています。それともバグですか?
違いを見つけるには、以下の例を参照して、通常ToString1()
とToString2()
/を比較してくださいToString3()
。
Imports System.Runtime.CompilerServices
Module CompilerExtensionsModule
' standard one, works as expected
<Extension>
Function ToString1(value As Integer) As String
Return value.ToString()
End Function
' obj isn't expected as parameter on actual usage, context is supplied instead
<Extension>
Function ToString2(obj As Object) As String
Return If(obj Is Nothing, "", obj.ToString())
End Function
' this is way how to have obj as parameter - first parameter is ignored
<Extension>
Function ToString3(base As Object, obj As Object) As String
Return If(obj Is Nothing, "", obj.ToString())
End Function
' let's try with something different than Object
<Extension>
Function ToStringClass1(obj As Class1) As String
Return obj.ToString()
End Function
End Module
クラスでの使用法:
ToString1(3) ' as expected - 1 parameter declared, 1 expected
ToString2() ' 1 parameter declared, no parameters expected in call
ToString3(Nothing) ' 2 parameters declared, 1 expected in call - passed as second parameter
追加された詳細: (最小限の完全な動作例 – 3 つのファイル – 上記のファイルを含む)
完全な呼び出しコンテキスト:クラス:
Public Class Class1
Sub Action1()
Dim value1 As Integer = 1
Dim obj1 As Object = Nothing
Dim obj2 As New Class1
Console.WriteLine(ToString1(value1))
Console.WriteLine(ToString2())
Console.WriteLine(ToString3(obj1))
Console.WriteLine(ToStringClass1())
End Sub
End Class
完全な呼び出しコンテキスト: Class1とは異なるクラス– 問題は投稿されていませんが、奇妙な効果:
Public Class Class2
Sub Action1()
Dim value1 As Integer = 1
Dim obj1 As Object = Nothing
Dim obj2 As New Class1
Console.WriteLine(ToString1(value1))
Console.WriteLine(ToString2())
Console.WriteLine(ToString3(obj1))
Console.WriteLine(ToStringClass1(obj2))
obj2.ToString2()
ToString2(obj2) ' INVALID - won't compile in any class (but will do in any module)
ToString3(obj2) ' EDIT: VALID because two parameters are actually supplied here
' EDIT (see comments below the answer):
CompilerExtensionsModule.ToString2(obj2) ' VALID - switching the context solves it
' Note: for ext.mehods of Object, this form of call is needed in any class
' Reason: any class is descendant of Object => VB wants to supply 1st parameter
' in calling context of class => use calling context of ext.module instead
End Sub
End Class
完全な呼び出しコンテキスト:モジュール– 問題なし:
Module Module1
Sub Main()
Dim value1 As Integer = 1
Dim obj1 As Object = Nothing
Dim obj2 As New Class1
Console.WriteLine(ToString1(value1))
Console.WriteLine(ToString2(obj1))
Console.WriteLine(ToString3(obj1, obj1))
Console.WriteLine(ToStringClass1(obj2))
' unlike in Class2, no issues here:
obj2.ToString2()
ToString2(obj2)
End Sub
End Module