Подтвердить что ты не робот

VB.NET: невозможно использовать метод расширения в экземпляре System.Object

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

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

Dim myObj2 = MyExtension(myObj1)
4b9b3361

Ответ 1

Вы не можете напрямую писать метод расширения для объекта, но с использованием дженериков вы можете добиться того же результата:

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

Ответ 2

Похоже, что поддержка методов расширения на объекте не является конструктивным решением в VB.

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

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

Ответ 3

Смотрите этот вопрос, который я задал некоторое время назад. В принципе, вы можете расширять 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 в С#, и вы поймете, что объяснение одно и то же.

Ответ 4

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

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

Он нуждается в переключении контекста из класса в модуль расширения:

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

Ответ 5

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

EDIT -

Добавлена ​​реализация метода расширения 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

Ответ 6

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

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

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