2010-07-12 10 views
34

Posso creare un metodo di estensione per tutte le sottoclassi di System.Object (tutto)?VB.NET: impossibile utilizzare il metodo di estensione sull'istanza System.Object

Esempio:

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

Le funzioni di cui sopra non funziona per istanza di oggetto:

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

Il compilatore non lo accetta, è il problema nel mio computer? :)

UPDATE
Il problema sembra verificarsi solo in VB, dove i membri di oggetto sono guardato-up per riflessione (late-bound).

AGGIORNAMENTO DOPO RISPOSTO
FYI, come VB ha un vantaggio che C# manca cioè membri di moduli importati vengono importati per la portata globale in modo da poter ancora utilizzare queste funzioni senza il loro involucro:

Dim myObj2 = MyExtension(myObj1) 

risposta

8

Non è possibile direttamente scrivere un metodo di estensione per oggetto, ma utilizzando farmaci generici si può ottenere lo stesso risultato:

<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 

Si noti che è possibile chiamare questo come un metodo di estensione su tutto tranne cose che sono dichiarati avere il tipo Object. Per quelli, devi chiamarlo direttamente (infallibile) o chiamare tramite casting (che potrebbe fallire, in quanto non esiste un'interfaccia univoca, quindi un po 'rischiosa).

-1

Certo che puoi, anche se potresti voler risparmiare ciò che fai qui per non ingombrare ogni oggetto. Un metodo di estensione che mi piace utilizzare per Object è un metodo chiamato IsIn() che funziona in modo simile all'istruzione SQL IN(). E 'bello poter dire cose come:

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 -

implementazione Aggiunto di Isin() metodo di estensione in basso per aiutare commentatore.

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

Avete provato questo codice? La terza riga (someObj) non funziona per me. – Shimmy

+0

Sì, questo funziona per me. Come hai scritto la tua versione del metodo di estensione IsIn()? Ho modificato il mio post per includere la mia implementazione per aiutarti. – mattmc3

+4

Se hai digitato 'someObj' come' Object' nel tuo codice, allora questo sicuramente dovrebbe * not * funzionare per te. –

36

Sembra che non supportano i metodi di estensione in oggetto è stata una decisione di progettazione 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.

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

+1

Risposta accolta per fornire il link di origine Microsoft. – Shimmy

12

Vedi this question I asked some time ago. Fondamentalmente, è possibile estendereObject in VB.NET se si desidera; ma per motivi di compatibilità a ritroso, nessuna variabile dichiarata come Object sarà in grado di utilizzare il metodo di estensione. Questo perché VB.NET supporta l'associazione tardiva su Object, quindi un tentativo di accedere a un metodo di estensione verrà ignorato a favore del tentativo di trovare un metodo con lo stesso nome dal tipo dell'oggetto in questione.

Quindi prendere questo metodo di estensione, ad esempio:

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

Questo metodo di estensione potrebbe essere utilizzato qui:

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

Ma non qui:

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

chiedetevi perché estensione i metodi non funzionano sulle variabili dynamic in C# e capirai che la spiegazione è lo stesso.

1

jmoreno's answernon può essere utilizzato con Option Strict On - getta di errore:

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

Ha bisogno di cambio di contesto da classe a modulo di estensione:

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