【发布时间】:2015-09-08 16:26:58
【问题描述】:
对象can be declared on Object but cannot be used like obj.ExtMethod() 的扩展方法。这是设计使然。另一方面,也可以使用任何扩展方法,如ExtMethod(obj)。 为什么在 Object 上声明的扩展方法的调用与在其他类型上声明的扩展方法不同? 我正在寻找这背后的逻辑。还是bug?
要发现差异,请参见下面的示例并将普通的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
完整的调用上下文: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
【问题讨论】:
-
请展示一个简短但完整的示例来说明问题。 (您的模块目前甚至无法为我编译。)我的 猜测 是您隐含地将
Me作为第一个参数传递.. -
@JonSkeet - 我的道歉 - 已修复...让我们现在删除这些 cmets,因为不再需要它们。
-
在
ToString3中你不使用第一个参数 - 为什么有它? -
@OneFineDay - 我不希望它在那里,请查看
ToString3()在课堂上调用时的示例。
标签: vb.net call extension-methods roslyn option-strict