2010-07-12 2 views
34

Могу ли я сделать метод расширения для всех подклассов System.Object (все)?VB.NET: невозможно использовать метод расширения в экземпляре 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, где члены объекта смотрели вверх по отражению (late-bound).

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

Dim myObj2 = MyExtension(myObj1) 

ответ

8

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

<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).

-1

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

ли проверить вас этот код? Третья строка (someObj) не работает для меня. – Shimmy

+0

Да, это работает для меня. Как вы написали свою версию метода расширения IsIn()? Я отредактировал свое сообщение, чтобы включить мою реализацию, чтобы помочь вам. – mattmc3

+4

Если вы вводили 'someObj' как' Object' в свой код, то это определенно должно * не * работать для вас. –

-4

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

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

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

+4

Моя проблема связана с VB. – Shimmy

36

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

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

+1

Аккументированный ответ для предоставления исходной ссылки Microsoft. – Shimmy

12

См this question I asked some time ago. В принципе, вы можетепродлить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#, и вы поймете, что объяснение тоже самое.

1

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

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

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

Dim text1 As String = MyExtModule.NullSafeToString(DataGridView1.Rows(0).Cells(0).Value) 
Смежные вопросы