Cómo comprobar si un objeto es de cierto tipo

102

Estoy pasando varios objetos a una subrutina para ejecutar el mismo proceso pero usando un objeto diferente cada vez. Por ejemplo, en un caso estoy usando un ListView y en otro caso estoy pasando un DropDownList.

Quiero verificar si el objeto que se pasa es un DropDownList y luego ejecutar algún código si lo es. ¿Cómo hago esto?

Mi código hasta ahora que no funciona:

Sub FillCategories(ByVal Obj As Object)
    Dim cmd As New SqlCommand("sp_Resources_Categories", Conn)
    cmd.CommandType = CommandType.StoredProcedure
    Obj.DataSource = cmd.ExecuteReader
    If Obj Is System.Web.UI.WebControls.DropDownList Then

    End If
    Obj.DataBind()
End Sub
Leah
fuente

Respuestas:

159

En VB.NET, debe utilizar el GetTypemétodo para recuperar el tipo de una instancia de un objeto y el GetType()operador para recuperar el tipo de otro tipo conocido.

Una vez que tenga los dos tipos, simplemente puede compararlos usando el Isoperador.

Entonces, su código debería estar escrito así:

Sub FillCategories(ByVal Obj As Object)
    Dim cmd As New SqlCommand("sp_Resources_Categories", Conn)
    cmd.CommandType = CommandType.StoredProcedure
    Obj.DataSource = cmd.ExecuteReader
    If Obj.GetType() Is GetType(System.Web.UI.WebControls.DropDownList) Then

    End If
    Obj.DataBind()
End Sub

También puede utilizar el TypeOfoperador en lugar del GetTypemétodo. Tenga en cuenta que esto prueba si su objeto es compatible con el tipo dado, no que sea del mismo tipo. Eso se vería así:

If TypeOf Obj Is System.Web.UI.WebControls.DropDownList Then

End If

Totalmente trivial e irrelevante: Tradicionalmente, los nombres de los parámetros se basan en camello (lo que significa que siempre comienzan con una letra minúscula) al escribir código .NET (ya sea VB.NET o C #). Esto los hace fáciles de distinguir de un vistazo de clases, tipos, métodos, etc.

Cody Grey
fuente
1
Gracias por tu respuesta. Probé ese código pero en realidad lo único es que no funciona con el operador '='. Tuve que cambiarlo a 'Is'. El error que tuve cuando era '=' era "Operador '=' no está definido para los tipos 'System.Type' y 'System.Type'".
Leah
1
@Leah: Sí, lo siento. Parece que debería empezar a prestar más atención al escribir las respuestas. TypeOfes probablemente una opción aún más simple, al menos en términos de legibilidad del código; También actualicé la respuesta con un ejemplo de eso.
Cody Gray
35
Hay una diferencia importante entre los dos, que es lo que me llevó a este artículo. La comprobación TypeOf devolverá True si el objeto es de una clase que hereda del tipo con el que está comprobando, mientras que GetType solo devolverá True si es exactamente la misma clase.
Abacus
Contrapunto totalmente trivial e irrelevante: a pesar de que VS CodeAnalysis se queja, todavía siento que los nombres de los argumentos son parte de la interfaz pública y también lo son PascalCase en mi código.
Mark Hurd
¿Existe una diferencia de rendimiento entre los dos? - ¿Qué pasa Select Case (Obj.GetType())con múltiples casos de prueba Vs múltiples IF TypeOf Obj is ...?
Luke T O'Brien
3

Algunos detalles más en relación con la respuesta de Cody Gray. Como me tomó un tiempo digerirlo, pensé que podría ser útil para otros.

Primero, algunas definiciones:

  1. Hay TypeNames, que son representaciones de cadena del tipo de un objeto, interfaz, etc. Por ejemplo, Bares un TypeName en Public Class Baro en Dim Foo as Bar. TypeNames podría verse como "etiquetas" utilizadas en el código para decirle al compilador qué definición de tipo buscar en un diccionario donde se describirían todos los tipos disponibles.
  2. Hay System.Typeobjetos que contienen un valor. Este valor indica un tipo; al igual Stringque a tomaría un texto o Inttomaría un número, excepto que estamos almacenando tipos en lugar de texto o números. Typelos objetos contienen las definiciones de tipo, así como su correspondiente TypeName.

En segundo lugar, la teoría:

  1. Foo.GetType()devuelve un Typeobjeto que contiene el tipo de la variable Foo. En otras palabras, le dice qué Fooes una instancia de.
  2. GetType(Bar)devuelve un Typeobjeto que contiene el tipo de TypeName Bar.
  3. En algunos casos, el tipo al que ha pertenecido un objeto Castes diferente del tipo del que se creó una instancia por primera vez. En el siguiente ejemplo, MyObj se convierte Integeren un Object:

    Dim MyVal As Integer = 42 Dim MyObj As Object = CType(MyVal, Object)

Entonces, ¿es MyObjde tipo Objecto de tipo Integer? MyObj.GetType()te dirá que es un Integer.

  1. Pero aquí viene la Type Of Foo Is Barfunción, que le permite determinar que una variable Fooes compatible con un TypeName Bar. Type Of MyObj Is Integery Type Of MyObj Is Objectambos devolverán True. En la mayoría de los casos, TypeOf indicará que una variable es compatible con un TypeName si la variable es de ese tipo o de un tipo que se deriva de él. Más información aquí: https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/operators/typeof-operator#remarks

La siguiente prueba ilustra bastante bien el comportamiento y el uso de cada una de las palabras clave y propiedades mencionadas.

Public Sub TestMethod1()

    Dim MyValInt As Integer = 42
    Dim MyValDble As Double = CType(MyValInt, Double)
    Dim MyObj As Object = CType(MyValDble, Object)

    Debug.Print(MyValInt.GetType.ToString) 'Returns System.Int32
    Debug.Print(MyValDble.GetType.ToString) 'Returns System.Double
    Debug.Print(MyObj.GetType.ToString) 'Returns System.Double

    Debug.Print(MyValInt.GetType.GetType.ToString) 'Returns System.RuntimeType
    Debug.Print(MyValDble.GetType.GetType.ToString) 'Returns System.RuntimeType
    Debug.Print(MyObj.GetType.GetType.ToString) 'Returns System.RuntimeType

    Debug.Print(GetType(Integer).GetType.ToString) 'Returns System.RuntimeType
    Debug.Print(GetType(Double).GetType.ToString) 'Returns System.RuntimeType
    Debug.Print(GetType(Object).GetType.ToString) 'Returns System.RuntimeType

    Debug.Print(MyValInt.GetType = GetType(Integer)) '# Returns True
    Debug.Print(MyValInt.GetType = GetType(Double)) 'Returns False
    Debug.Print(MyValInt.GetType = GetType(Object)) 'Returns False

    Debug.Print(MyValDble.GetType = GetType(Integer)) 'Returns False
    Debug.Print(MyValDble.GetType = GetType(Double)) '# Returns True
    Debug.Print(MyValDble.GetType = GetType(Object)) 'Returns False

    Debug.Print(MyObj.GetType = GetType(Integer)) 'Returns False
    Debug.Print(MyObj.GetType = GetType(Double)) '# Returns True
    Debug.Print(MyObj.GetType = GetType(Object)) 'Returns False

    Debug.Print(TypeOf MyObj Is Integer) 'Returns False
    Debug.Print(TypeOf MyObj Is Double) '# Returns True
    Debug.Print(TypeOf MyObj Is Object) '# Returns True


End Sub

EDITAR

También puede utilizar Information.TypeName(Object)para obtener el TypeName de un objeto determinado. Por ejemplo,

Dim Foo as Bar
Dim Result as String
Result = TypeName(Foo)
Debug.Print(Result) 'Will display "Bar"
Ama
fuente