VB.NET:无法在 System.Object 实例上使用扩展方法

发布于 2024-09-09 01:51:52 字数 665 浏览 7 评论 0原文

我可以为 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)

Can I make an Extension method for all the subclasses of System.Object (everything)?

Example:

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

The above functions won't work for object instance:

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

The compiler does not accept it, is the problem in my computer? :)

UPDATE
The problem seems to occur only in VB, where members of object are looked-up by reflection (late-bound).

UPDATE AFTER ANSWERED
FYI, as vb has an advantage that C# lacks that is, members of imported Modules are imported to the global scope so you can still use this functions without their wrapper:

Dim myObj2 = MyExtension(myObj1)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

不羁少年 2024-09-16 01:51:52

似乎不支持对象上的扩展方法是 VB 中的设计决策。

因此,我们唯一能做的就是
防止扩展方法
彻底打破现有的后期
绑定代码是为了防止他们
用于任何键入为
对象。

链接

It seems like not supporting Extension methods on Object was a design decision in VB.

As a result, the only way we could
prevent extension methods from
completely breaking existing late
bound code was to prevent them from
being used on anything typed as
object.

Link

耀眼的星火 2024-09-16 01:51:52

请参阅我不久前问过的这个问题。基本上,如果您愿意,您可以在 VB.NET 中扩展对象;但出于向后兼容性的原因,声明为 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()

问问自己为什么扩展方法不适用于 C# 中的 dynamic 变量,您就会明白其中的解释是一样的。

See this question I asked some time ago. Basically, you can extend Object in VB.NET if you want; but for backwards compatibility reasons, no variable declared as Object will be able to use your extension method. This is because VB.NET supports late binding on Object, so an attempt to access an extension method will be ignored in favor of trying to find a method of the same name from the type of the object in question.

So take this extension method, for example:

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

This extension method could be used here:

' 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()

But not here:

' 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()

Ask yourself why extension methods don't work on dynamic variables in C#, and you'll realize the explanation is the same.

隐诗 2024-09-16 01:51:52

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

<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 类型。对于这些,您必须直接调用它(完整的证明)或通过强制转换调用(这可能会失败,因为没有通用接口,所以有点冒险)。

You can not directly write an extension method for Object, but using generics you can achieve the same result:

<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

Note that you can call this as an extension method on everything except things that are declared to have the type Object. For those, you have to either call it directly (full proof) or call via casting (which could fail, as there is no univesal interface, so somewhat chancy).

北方的韩爷 2024-09-16 01:51:52

jmoreno的答案 不能与Option Strict On一起使用 - 它会抛出错误:

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

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

Dim text1 As String = MyExtModule.NullSafeToString(DataGridView1.Rows(0).Cells(0).Value)

jmoreno's answer cannot be used with Option Strict On – it throws error:

BC30512 Option Strict On disallows implicit conversions from 'Object' to 'Integer'.

It needs context switch from class to extension module:

Dim text1 As String = MyExtModule.NullSafeToString(DataGridView1.Rows(0).Cells(0).Value)
风情万种。 2024-09-16 01:51:52

当然可以,尽管您可能希望节省在这里所做的事情,以免弄乱每个对象。我喜欢对 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

Sure you can, though you might want to be sparing about what you do here so as not to clutter every object. An extension method I like using for Object is a method called IsIn() that functions similarly to the SQL IN() statement. It's nice to say things like:

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

EDIT -

Added implementation of IsIn() extension method below to help commenter.

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
夏雨凉 2024-09-16 01:51:52

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

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

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

If you do too many extensions on object intellisence might become less useful, but it's perfectly valid.

Here's an example of an extension method on object for object information:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文