So überprüfen Sie, ob ein Objekt ein bestimmter Typ ist

102

Ich übergebe verschiedene Objekte an eine Unterroutine, um denselben Prozess auszuführen, aber jedes Mal ein anderes Objekt zu verwenden. In einem Fall verwende ich beispielsweise eine ListView und in einem anderen Fall übergebe ich eine DropDownList.

Ich möchte überprüfen, ob das übergebene Objekt eine DropDownList ist, und dann Code ausführen, falls dies der Fall ist. Wie mache ich das?

Mein bisheriger Code, der nicht funktioniert:

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
quelle

Antworten:

159

In VB.NET müssen Sie die GetTypeMethode verwenden , um den Typ einer Instanz eines Objekts abzurufen , und den GetType()Operator , um den Typ eines anderen bekannten Typs abzurufen.

Sobald Sie die beiden Typen haben, können Sie sie einfach mit dem IsOperator vergleichen.

Ihr Code sollte also eigentlich so geschrieben sein:

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

Sie können auch den TypeOfOperator anstelle der GetTypeMethode verwenden. Beachten Sie, dass hiermit geprüft wird, ob Ihr Objekt mit dem angegebenen Typ kompatibel ist , nicht, dass es vom selben Typ ist. Das würde so aussehen:

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

End If

Völlig trivialer, irrelevanter Nitpick: Traditionell werden die Namen von Parametern beim Schreiben von .NET-Code (entweder VB.NET oder C #) camelCased (dh sie beginnen immer mit einem Kleinbuchstaben). Dadurch sind sie auf einen Blick leicht von Klassen, Typen, Methoden usw. zu unterscheiden.

Cody Grey
quelle
1
Danke für deine Antwort. Ich habe diesen Code ausprobiert, aber das einzige ist, dass er mit dem Operator '=' nicht funktioniert. Ich musste es in "Ist" ändern. Der Fehler, den ich hatte, als es '=' war, war "Operator '=' ist nicht für die Typen 'System.Type' und 'System.Type' definiert."
Leah
1
@Leah: Ja, tut mir leid. Sieht so aus, als sollte ich beim Schreiben von Antworten mehr Aufmerksamkeit schenken. TypeOfist wahrscheinlich eine noch einfachere Option, zumindest in Bezug auf die Lesbarkeit des Codes; Ich habe die Antwort auch mit einem Beispiel dafür aktualisiert.
Cody Gray
35
Es gibt einen wichtigen Unterschied zwischen den beiden, was mich zu diesem Beitrag geführt hat. Die TypeOf-Prüfung gibt True zurück, wenn das Objekt einer Klasse angehört, die von dem Typ erbt, gegen den Sie prüfen, während GetType True nur zurückgibt, wenn es genau dieselbe Klasse ist.
Abacus
Völlig trivialer, irrelevanter Kontrapunkt: Auch wenn sich die VS CodeAnalysis beschwert, sind die Argumentnamen meiner Meinung nach Teil der öffentlichen Schnittstelle, ebenso wie PascalCase in meinem Code.
Mark Hurd
Gibt es einen Leistungsunterschied zwischen den beiden? - Was ist Select Case (Obj.GetType())mit mehreren Testfällen gegen mehrere IF TypeOf Obj is ...?
Luke T O'Brien
3

Einige weitere Details in Bezug auf die Antwort von Cody Gray. Da ich einige Zeit gebraucht habe, um es zu verdauen, dachte ich, dass es für andere nützlich sein könnte.

Zunächst einige Definitionen:

  1. Es gibt TypeNames, bei denen es sich um Zeichenfolgendarstellungen des Typs eines Objekts, einer Schnittstelle usw. handelt. Beispielsweise Barhandelt es sich um einen TypeName in Public Class Baroder in Dim Foo as Bar. TypeNames können als "Labels" angesehen werden, die im Code verwendet werden, um dem Compiler mitzuteilen, nach welcher Typdefinition in einem Wörterbuch gesucht werden soll, in dem alle verfügbaren Typen beschrieben werden.
  2. Es gibt System.TypeObjekte, die einen Wert enthalten. Dieser Wert gibt einen Typ an. Genau wie ein StringText oder Inteine Zahl, außer wir speichern Typen anstelle von Text oder Zahlen. TypeObjekte enthalten die Typdefinitionen sowie den entsprechenden Typnamen.

Zweitens die Theorie:

  1. Foo.GetType()Gibt ein TypeObjekt zurück, das den Typ für die Variable enthält Foo. Mit anderen Worten, es sagt Ihnen, was Fooeine Instanz von ist.
  2. GetType(Bar)TypeGibt ein Objekt zurück, das den Typ für den Typnamen enthält Bar.
  3. In einigen Fällen unterscheidet sich der Typ, in dem ein Objekt war Cast, von dem Typ, von dem ein Objekt zuerst instanziiert wurde. Im folgenden Beispiel ist MyObj eine IntegerBesetzung in Object:

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

Also, ist MyObjvom Typ Objectoder vom Typ Integer? MyObj.GetType()Ich werde dir sagen, dass es ein ist Integer.

  1. Aber hier kommt die Type Of Foo Is BarFunktion, mit der Sie feststellen können, Fooob eine Variable mit einem TypeName kompatibel ist Bar. Type Of MyObj Is Integerund Type Of MyObj Is Objectbeide werden True zurückgeben. In den meisten Fällen gibt TypeOf an, dass eine Variable mit einem TypeName kompatibel ist, wenn die Variable von diesem Typ oder einem davon abgeleiteten Typ ist. Weitere Informationen finden Sie hier: https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/operators/typeof-operator#remarks

Der folgende Test veranschaulicht das Verhalten und die Verwendung der einzelnen genannten Schlüsselwörter und Eigenschaften recht gut.

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

BEARBEITEN

Sie können auch Information.TypeName(Object)den Typnamen eines bestimmten Objekts abrufen. Beispielsweise,

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