39

我可以为System.Object(所有)的所有子类创建一个扩展方法吗?

例子:

<Extension>
Public Function MyExtension(value As Object) As Object
    Return value
End Function

上述函数不适用于对象实例:

Dim myObj1 As New Object()
Dim myObj2 = myObj1.MyExtension()

编译器不接受,是我电脑的问题吗?:)

更新问题似乎只发生在VB中,其中对象的成员通过反射(后期绑定
) 查找。

回答后更新
仅供参考,因为 vb 具有 C# 缺乏的优势,即导入模块的成员被导入到全局范围,因此您仍然可以在没有包装器的情况下使用此函数:

Dim myObj2 = MyExtension(myObj1)
4

6 回答 6

45

似乎不支持 Object 的扩展方法是 VB 中的设计决定。

因此,我们可以防止扩展方法完全破坏现有的后期绑定代码的唯一方法是防止它们被用于任何类型为对象的东西。

http://blogs.msdn.com/b/vbteam/archive/2007/01/24/extension-methods-and-late-binding-extension-methods-part-4.aspx

于 2010-07-12T12:31:16.960 回答
14

请参阅我前一段时间提出的这个问题。基本上,您可以根据需要在 VB.NET 中进行 扩展 Object;但是出于向后兼容性的原因,没有声明为 as 的变量Object将能够使用您的扩展方法。这是因为 VB.NET 支持对 的后期绑定Object,因此访问扩展方法的尝试将被忽略,而是尝试从相关对象的类型中找到同名的方法。

所以采取这种扩展方法,例如:

<Extension()>
Public Sub Dump(ByVal obj As Object)
    Console.WriteLine(obj)
End Sub

这种扩展方法可以在这里使用:

' Note: here we are calling the Dump extension method on a variable '
' typed as String, which works because String (like all classes) '
' inherits from Object. '
Dim str As String = "Hello!"
str.Dump()

但不是在这里:

' Here we attempt to call Dump on a variable typed as Object; but '
' this will not work since late binding is a feature that came before '
' extension methods. '
Dim obj As New Object
obj.Dump()

问问自己为什么扩展方法不适dynamic用于 C# 中的变量,你会发现解释是一样的。

于 2010-07-12T12:58:23.360 回答
13

您不能直接为 Object 编写扩展方法,但使用泛型可以达到相同的结果:

<Extension()>
Public Function NullSafeToString(Of T)(this As T) As String
    If this is Nothing Then
       Return String.Empty
    End If
    Return this.ToString()
End Function

请注意,除了声明为 Object 类型的事物之外,您可以将其作为扩展方法调用。对于那些,您必须直接调用它(完全证明)或通过强制转换调用(这可能会失败,因为没有通用接口,所以有点机会)。

于 2015-07-23T00:35:08.500 回答
1

jmoreno 的答案 不能用于Option Strict On- 它会引发错误:

BC30512 Option Strict On 不允许从“对象”到“整数”的隐式转换。

它需要从类到扩展模块的上下文切换:

Dim text1 As String = MyExtModule.NullSafeToString(DataGridView1.Rows(0).Cells(0).Value)
于 2015-09-08T12:48:09.137 回答
0

当然可以,尽管您可能希望对您在这里所做的事情有所保留,以免弄乱每个对象。我喜欢对 Object 使用的一个扩展方法是一个名为 IsIn() 的方法,它的功能类似于 SQL IN() 语句。很高兴这样说:

If someString.IsIn("a", "b", "c") Then
   DoSomething()
Else If someInt.IsIn(1, 2, 3) Then
   DoSomethingElse()
Else If someObj.IsIn(1, "q", #7/1/2010#) Then
   DoSomethingTheThirdWay()
End If

编辑 -

在下方添加了 IsIn() 扩展方法的实现以帮助评论者。

Imports System.Runtime.CompilerServices

Public Module ObjectExtensions
  <Extension()>
  Public Function IsIn(obj As Object, ParamArray values() As Object) As Boolean
    For Each val As Object In values
      If val.Equals(obj) Then Return True
    Next
    Return False
  End Function
End Module
于 2010-07-12T11:14:48.517 回答
-5

如果您对对象智能进行太多扩展,可能会变得不那么有用,但它是完全有效的。

以下是对象信息的对象扩展方法示例:

http://www.developer.com/net/csharp/article.php/3718806/NET-Tip-Using-Extension-Methods.htm

于 2010-07-12T11:34:27.507 回答