Come verificare se un oggetto è di un certo tipo


102

Sto passando vari oggetti a una subroutine per eseguire lo stesso processo ma utilizzo ogni volta un oggetto diverso. Ad esempio, in un caso sto usando un ListView e in un altro sto passando un DropDownList.

Voglio controllare se l'oggetto passato è un DropDownList, quindi eseguire del codice se lo è. Come faccio a fare questo?

Il mio codice finora che non funziona:

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

Risposte:


160

In VB.NET, è necessario utilizzare il GetTypemetodo per recuperare il tipo di un'istanza di un oggetto e l' GetType()operatore per recuperare il tipo di un altro tipo noto.

Una volta che hai i due tipi, puoi semplicemente confrontarli usando l' Isoperatore.

Quindi il tuo codice dovrebbe effettivamente essere scritto in questo modo:

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

È inoltre possibile utilizzare l' TypeOfoperatore invece del GetTypemetodo. Nota che questo verifica se il tuo oggetto è compatibile con il tipo dato, non che sia dello stesso tipo. Sarebbe simile a questo:

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

End If

Totalmente banale, irrilevante nitpick: tradizionalmente, i nomi dei parametri sono camelCased (il che significa che iniziano sempre con una lettera minuscola) quando si scrive codice .NET (VB.NET o C #). Ciò li rende facilmente distinguibili a colpo d'occhio da classi, tipi, metodi, ecc.


1
Grazie per la tua risposta. Ho provato quel codice ma in realtà l'unica cosa è che non funziona con l'operatore "=". Ho dovuto cambiarlo in "È". L'errore che ho riscontrato quando era "=" era "Operator '=' non è definito per i tipi" System.Type "e" System.Type "."
Leah

1
@ Sì: Sì, mi dispiace per questo. Sembra che dovrei iniziare a prestare più attenzione quando scrivo le risposte. TypeOfè probabilmente un'opzione ancora più semplice, almeno in termini di leggibilità del codice; Ho aggiornato anche la risposta con un esempio di questo.
Cody Grey

35
C'è una differenza importante tra i due, che è ciò che mi ha portato a questo post. Il controllo TypeOf restituirà True se l'oggetto è di una classe che eredita dal tipo contro cui stai controllando, mentre GetType restituirà True solo se è esattamente la stessa classe.
Abaco

Contrappunto totalmente banale e irrilevante: anche se VS CodeAnalysis si lamenta, sento ancora che i nomi degli argomenti fanno parte dell'interfaccia pubblica e lo sono anche PascalCase nel mio codice.
Mark Hurd

C'è una differenza di prestazioni tra i due? - E Select Case (Obj.GetType())con più casi di test Vs multipli IF TypeOf Obj is ...?
Luke T O'Brien

3

Qualche dettaglio in più in relazione alla risposta di Cody Gray. Dato che mi ci è voluto del tempo per digerirlo, ho pensato che potesse essere utile ad altri.

Innanzitutto, alcune definizioni:

  1. Ci sono TypeName, che sono rappresentazioni di stringa del tipo di un oggetto, interfaccia, ecc. Ad esempio, Barè un TypeName in Public Class Baro in Dim Foo as Bar. I TypeNames possono essere visti come "etichette" utilizzate nel codice per indicare al compilatore quale definizione di tipo cercare in un dizionario in cui verranno descritti tutti i tipi disponibili.
  2. Ci sono System.Typeoggetti che contengono un valore. Questo valore indica un tipo; proprio come a Stringprenderebbe del testo o un Intprenderebbe un numero, eccetto che stiamo memorizzando tipi invece di testo o numeri. Typegli oggetti contengono le definizioni del tipo, nonché il corrispondente TypeName.

Secondo, la teoria:

  1. Foo.GetType()restituisce un Typeoggetto che contiene il tipo per la variabile Foo. In altre parole, ti dice cos'è Fooun'istanza di.
  2. GetType(Bar)restituisce un Typeoggetto che contiene il tipo per TypeName Bar.
  3. In alcuni casi, il tipo a cui è stato un oggetto Castè diverso dal tipo di cui è stata creata l'istanza per la prima volta. Nell'esempio seguente, MyObj è un Integercast in un Object:

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

Quindi, è MyObjdi tipo Objecto di tipo Integer? MyObj.GetType()ti dirà che è un file Integer.

  1. Ma ecco che arriva la Type Of Foo Is Barfunzionalità, che ti consente di accertarti che una variabile Fooè compatibile con un TypeName Bar. Type Of MyObj Is Integered Type Of MyObj Is Objectentrambi restituiranno True. Nella maggior parte dei casi, TypeOf indicherà che una variabile è compatibile con un TypeName se la variabile è di quel tipo o di un tipo che ne deriva. Maggiori informazioni qui: https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/operators/typeof-operator#remarks

Il test seguente illustra abbastanza bene il comportamento e l'utilizzo di ciascuna delle parole chiave e delle proprietà menzionate.

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

MODIFICARE

È inoltre possibile utilizzare Information.TypeName(Object)per ottenere il TypeName di un determinato oggetto. Per esempio,

Dim Foo as Bar
Dim Result as String
Result = TypeName(Foo)
Debug.Print(Result) 'Will display "Bar"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.