VB.NET: невозможно использовать метод Extension в экземпляре System.Object - PullRequest
35 голосов
/ 12 июля 2010

Могу ли я создать метод Extension для всех подклассов System.Object (все)?

Пример:

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

Указанные выше функции не будут работать для экземпляра объекта:

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

Компилятор не принимает это, проблема в моем компьютере? :)

UPDATE
Кажется, проблема возникает только в VB, где члены объекта просматриваются по отражению ( поздний предел ).

ОБНОВЛЕНИЕ ПОСЛЕ ОТВЕТА
К вашему сведению, поскольку у vb есть преимущество, которого нет в C #, то есть члены импортируемых модулей импортируются в глобальную область, поэтому вы все еще можете использовать эти функции без их оболочки:

Dim myObj2 = MyExtension(myObj1)

Ответы [ 6 ]

40 голосов
/ 12 июля 2010

Кажется, что не поддержка методов Extension в Object была дизайнерским решением в VB.

В результате, единственный способ, которым мы могли предотвратить методы расширения, чтобы полностью сломать существующий код с поздней привязкой, состоял в том, чтобы предотвратитьих от использования на чем-либо, напечатанном как объект.

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

13 голосов
/ 12 июля 2010

См. этот вопрос я задал некоторое время назад .По сути, вы можете расширить Object в 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()

Спросите себя, почему методы расширения не работают с dynamic переменными в C #, и вы поймете, что объяснение то же самое.

9 голосов
/ 23 июля 2015

Вы не можете напрямую написать метод расширения для 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. Для них вы должны либо вызвать его напрямую (защита от дурака), либо вызвать через кастинг (что может привести к сбою, так как нет универсального интерфейса, поэтому что-то не так).

1 голос
/ 08 сентября 2015

ответ jmoreno нельзя использовать с Option Strict On - выдает ошибку:

BC30512 Option Strict On запрещает неявные преобразования из 'Object' в'Integer'.

Требуется переключение контекста с класса на модуль расширения:

Dim text1 As String = MyExtModule.NullSafeToString(DataGridView1.Rows(0).Cells(0).Value)
0 голосов
/ 12 июля 2010

Если вы сделаете слишком много расширений на объектном интеллекте, это может стать менее полезным, но это совершенно правильно.

Вот пример метода расширения объекта для информации об объекте:

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

0 голосов
/ 12 июля 2010

Конечно, вы можете, хотя вы, возможно, захотите пощадить то, что вы делаете здесь, чтобы не загромождать каждый объект. Метод расширения, который мне нравится использовать для 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
...