2010-07-12 13 views
34

¿Puedo hacer un método de extensión para todas las subclases de System.Object (todo)?VB.NET: imposible de usar Método de extensión en System.Object instancia

Ejemplo:

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

Las funciones anteriores no funcionarán para instancia de objeto:

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

El compilador no lo acepta, es el problema en mi equipo? :)

ACTUALIZACIÓN
El problema parece ocurrir sólo en VB, donde los miembros del objeto son vistos en marcha por la reflexión (late-bound).

AFTER UPDATE ANSWERED
FYI, como VB tiene una ventaja que C# carece es decir, los miembros de los módulos importados se importan al ámbito mundial por lo que aún puede utilizar estas funciones sin su envoltorio:

Dim myObj2 = MyExtension(myObj1) 

Respuesta

8

No se puede directamente escribir un método de extensión para el objeto, pero el uso de los genéricos se puede lograr el mismo resultado:

<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 

Tenga en cuenta que usted puede llamar a esto como un método de extensión en todo excepto cosas que están declarados para tener el tipo Object. Para ellos, tienes que llamarlo directamente (a prueba de tontos) o llamar a través de un casting (que podría fallar, ya que no hay una interfaz única, tan un tanto arriesgada).

-1

Claro que puedes, aunque es posible que quieras ser cuidadoso con lo que haces aquí para no ocupar todos los objetos. Un método de extensión que me gusta usar para Object es un método llamado IsIn() que funciona de forma similar a la instrucción SQL IN(). Es bueno que decir cosas como:

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 

EDITAR -

aplicación Agregado de Isin() método de extensión de abajo para ayudar comentarista.

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

¿Se han probado este código? La tercera línea (someObj) no funciona para mí. – Shimmy

+0

Sí, esto funciona para mí. ¿Cómo escribiste tu versión del método de extensión IsIn()? He editado mi publicación para incluir mi implementación para ayudarte. – mattmc3

+4

Si escribió 'someObj' como' Object' en su código, entonces definitivamente * no * debería funcionar para usted. –

36

Parece que no apoyar métodos de extensión en el objeto fue una decisión de diseño en 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

Respuesta compensada para proporcionar el enlace de origen de Microsoft. – Shimmy

12

Ver this question I asked some time ago. Básicamente, usted puedeextiendaObject en VB.NET si lo desea; pero por razones de compatibilidad con versiones anteriores, ninguna variable declarada como Object podrá usar su método de extensión. Esto se debe a que VB.NET admite el enlace tardío en Object, por lo que se ignorará un intento de acceder a un método de extensión a favor de intentar encontrar un método del mismo nombre del tipo del objeto en cuestión.

Así que este método de extensión, por ejemplo:

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

Este método de extensión se podría utilizar aquí:

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

Pero no aquí:

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

preguntarse por qué extensión los métodos no funcionan en las variables dynamic en C#, y se dará cuenta de que la explicación es lo mismo.

1

jmoreno's answerno se puede utilizar con Option Strict On - arroja error:

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

Se necesita cambio de contexto de la clase de módulo de extensión:

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