Ich habe viele Leute gesehen, die den folgenden Code verwenden:
Type t = typeof(obj1);
if (t == typeof(int))
// Some code here
Aber ich weiß, dass Sie das auch tun können:
if (obj1.GetType() == typeof(int))
// Some code here
Oder dieses:
if (obj1 is int)
// Some code here
Persönlich denke ich, dass der letzte der sauberste ist, aber fehlt mir etwas? Welches ist das beste oder ist es eine persönliche Präferenz?
as
!as
ist aber nicht wirklich Typprüfung ...as
ist sicherlich eine Form der Typprüfung, genauso wie esis
ist! Es wird effektivis
hinter den Kulissen verwendet und überall in MSDN an Orten verwendet, an denen es die Code-Sauberkeit im Vergleich zu verbessertis
. Anstatt zuerst nachzuschlagenis
, wird durch einen Aufrufas
eine gebrauchsfertige typisierte Variable erstellt: Wenn sie null ist, antworten Sie entsprechend. Andernfalls fahren Sie fort. Sicherlich etwas, das ich gesehen und ziemlich oft benutzt habe.as
/is
(behandelt in stackoverflow.com/a/27813381/477420 ), vorausgesetzt, die semantische Funktion für Ihren Fall.GetType
Methode, auf die Sie verlinken, ist inSystem.Reflection.Assembly
- eine völlig andere Methode und hier irrelevant.Antworten:
Alle sind unterschiedlich.
typeof
Nimmt einen Typnamen (den Sie zur Kompilierungszeit angeben).GetType
Ruft den Laufzeittyp einer Instanz ab.is
Gibt true zurück, wenn sich eine Instanz im Vererbungsbaum befindet.Beispiel
Ja. T ist immer der Typ des Ausdrucks. Denken Sie daran, dass eine generische Methode im Grunde eine ganze Reihe von Methoden mit dem entsprechenden Typ ist. Beispiel:
quelle
new Dog().GetType() is Animal
gibt false zurück (und auch Ihre andere Version), da.GetType()
ein Objekt vom Typ zurückgegebenType
wird undType
kein Objekt istAnimal
.Verwenden
typeof
Sie diese Option, wenn Sie den Typ zur Kompilierungszeit abrufen möchten . VerwendenGetType
Sie diese Option, wenn Sie den Typ zur Ausführungszeit abrufen möchten . Es gibt selten Fälle, die verwendet werden müssen,is
da es sich um eine Umwandlung handelt, und in den meisten Fällen wird die Variable trotzdem umgewandelt.Es gibt eine vierte Option, die Sie nicht in Betracht gezogen haben (insbesondere, wenn Sie ein Objekt in den Typ umwandeln möchten, den Sie ebenfalls finden). das ist zu verwenden
as
.Dies verwendet nur eine Besetzung,
während dieser Ansatz:erfordert zwei .Update (Januar 2020):
Beispiel:
quelle
is
noch eine Besetzung durch?typeof()
, und diese Antwort schlägt nicht vor, dass Sie dies können. Sie übergeben stattdessen den Typ, dhtypeof(string)
funktioniert,typeof("foo")
funktioniert nicht.is
die Besetzung als solche ausgeführt wird, sondern eine besondere Operation in IL.if (obj is Foo foo) { /* use foo here */ }
1.
Dies ist unzulässig, da
typeof
nur Typen und keine Variablen verwendet werden. Ich gehe davon aus, dass obj1 eine Variable ist. Auf diese Weisetypeof
ist es also statisch und erledigt seine Arbeit zur Kompilierungszeit anstatt zur Laufzeit.2.
Dies ist,
true
wennobj1
es genau vom Typ istint
. Wennobj1
abgeleitet vonint
, wird die if-Bedingung seinfalse
.3.
Dies ist,
true
wennobj1
es sich um eineint
handelt oder wenn es von einer aufgerufenen Klasse abgeleitetint
ist oder wenn eine aufgerufene Schnittstelle implementiert wirdint
.quelle
Dies ist ein Fehler. Der Operator typeof in C # kann nur Typnamen annehmen, keine Objekte.
Dies wird funktionieren, aber vielleicht nicht so, wie Sie es erwarten würden. Wie Sie hier gezeigt haben, ist dies für Werttypen akzeptabel. Für Referenztypen wird jedoch nur true zurückgegeben, wenn der Typ genau derselbe Typ ist und nicht etwas anderes in der Vererbungshierarchie. Zum Beispiel:
Dies würde drucken
"o is something else"
, weil die Art dero
istDog
, nichtAnimal
. Sie können dies jedoch zum Laufen bringen, wenn Sie dieIsAssignableFrom
Methode derType
Klasse verwenden.Diese Technik hinterlässt jedoch immer noch ein großes Problem. Wenn Ihre Variable null ist,
GetType()
löst der Aufruf von eine NullReferenceException aus. Damit es richtig funktioniert, müssen Sie Folgendes tun:Damit haben Sie ein gleichwertiges Verhalten des
is
Schlüsselworts. Wenn dies das gewünschte Verhalten ist, sollten Sie daher dasis
Schlüsselwort verwenden, das lesbarer und effizienter ist.In den meisten Fällen ist das
is
Schlüsselwort jedoch immer noch nicht das, was Sie wirklich wollen, da es normalerweise nicht ausreicht, nur zu wissen, dass ein Objekt von einem bestimmten Typ ist. Normalerweise wollen Sie tatsächlich nutzen das Objekt als Instanz dieses Typs, die es auch erfordert Gießen. Und so können Sie feststellen, dass Sie Code wie folgt schreiben:Dadurch überprüft die CLR den Objekttyp bis zu zweimal. Es wird einmal überprüft, um den
is
Bediener zufrieden zu stellen , und wenn dieso
tatsächlich derAnimal
Fall ist, wird es erneut überprüft, um die Besetzung zu validieren.Es ist effizienter, dies stattdessen zu tun:
Der
as
Operator ist eine Besetzung, die keine Ausnahme auslöst, wenn sie fehlschlägt, sondern zurückkehrtnull
. Auf diese Weise überprüft die CLR den Objekttyp nur einmal, und danach müssen wir nur noch eine Nullprüfung durchführen, was effizienter ist.Aber Vorsicht: Viele Menschen geraten mit in eine Falle
as
. Da es keine Ausnahmen gibt, betrachten einige Leute es als "sichere" Besetzung, und sie verwenden es ausschließlich und meiden reguläre Besetzungen. Dies führt zu solchen Fehlern:In diesem Fall wird der Entwickler deutlich unter der Annahme , dass
o
wird immer eine seinAnimal
, und solange ihre Annahme richtig ist, funktioniert alles einwandfrei. Aber wenn sie falsch liegen, dann ist das, was sie hier haben, einNullReferenceException
. Mit einer regulären Besetzung hätten sieInvalidCastException
stattdessen eine bekommen , die das Problem genauer identifiziert hätte.Manchmal ist dieser Fehler schwer zu finden:
Dies ist ein weiterer Fall, in dem der Entwickler eindeutig erwartet
o
, dass diesAnimal
jedes Mal der Fall ist. Dies ist jedoch im Konstruktor, in dem dieas
Besetzung verwendet wird, nicht offensichtlich . Es ist nicht offensichtlich, bis Sie zu derInteract
Methode gelangen, bei deranimal
erwartet wird, dass das Feld positiv zugewiesen wird. In diesem Fall kommt es nicht nur zu einer irreführenden Ausnahme, sondern sie wird erst viel später ausgelöst, als der eigentliche Fehler aufgetreten ist.Zusammenfassend:
Wenn Sie nur wissen müssen, ob ein Objekt von einem Typ ist oder nicht, verwenden Sie
is
.Wenn Sie ein Objekt als Instanz eines bestimmten Typs behandeln müssen, aber nicht sicher sind, ob das Objekt von diesem Typ ist, verwenden Sie es
as
und suchen Sie nachnull
.Wenn Sie ein Objekt als Instanz eines bestimmten Typs behandeln müssen und das Objekt von diesem Typ sein soll, verwenden Sie eine reguläre Besetzung.
quelle
o is Animal
, dass die CLR prüfen muss, ob der Typ der Variablen eino
istAnimal
. Das zweite Mal wird geprüft, wann die Anweisung eingefügt wird((Animal)o).Speak()
. Anstatt zweimal zu prüfen, überprüfen Sie einmal mitas
.Wenn Sie C # 7 verwenden, ist es Zeit für ein Update von Andrew Hares großartiger Antwort. Der Mustervergleich hat eine nette Verknüpfung eingeführt, die uns eine typisierte Variable im Kontext der if-Anweisung gibt, ohne dass eine separate Deklaration / Besetzung und Prüfung erforderlich ist:
Für eine einzelne Besetzung wie diese sieht das ziemlich überwältigend aus, aber es scheint wirklich, wenn viele mögliche Typen in Ihre Routine kommen. Das Folgende ist der alte Weg, um zweimaliges Casting zu vermeiden:
Es hat mich immer gestört, diesen Code so weit wie möglich zu verkleinern und doppelte Besetzungen desselben Objekts zu vermeiden. Das Obige ist gut komprimiert und weist folgende Muster auf:
BEARBEITEN: Die längere neue Methode wurde aktualisiert, um einen Schalter gemäß Palecs Kommentar zu verwenden.
quelle
switch
Erklärung mit Mustervergleich ist in diesem Fall ratsam.if (obj1 is int integerValue) { integerValue++; }
Ich hatte eine
Type
Eigenschaft zum Vergleichen und konnte sie nicht verwendenis
(wiemy_type is _BaseTypetoLookFor
), aber ich konnte diese verwenden:Beachten Sie dies
IsInstanceOfType
undIsAssignableFrom
kehren Sie zurück,true
wenn Sie dieselben Typen vergleichen, wobei IsSubClassOf zurückgibtfalse
. UndIsSubclassOf
funktioniert nicht an Schnittstellen, wo die anderen beiden tun. (Siehe auch diese Frage und Antwort .)quelle
Ich bevorzuge ist
Das heißt, wenn Sie verwenden ist , sind Sie wahrscheinlich nicht Vererbung richtig verwenden.
Angenommen, diese Person: Entität und dieses Tier: Entität. Feed ist eine virtuelle Methode in Entity (um Neil glücklich zu machen)
Lieber
quelle
Ich glaube, der letzte befasst sich auch mit der Vererbung (z. B. Hund ist Tier == wahr), was in den meisten Fällen besser ist.
quelle
Es kommt darauf an, was ich mache. Wenn ich einen Bool-Wert benötige (z. B. um festzustellen, ob ich in einen Int umwandle), verwende ich
is
. Wenn ich den Typ aus irgendeinem Grund tatsächlich brauche (z. B. um zu einer anderen Methode überzugehen), werde ich ihn verwendenGetType()
.quelle
Der letzte ist sauberer, offensichtlicher und sucht auch nach Subtypen. Die anderen prüfen nicht auf Polymorphismus.
quelle
Wird verwendet, um das System.Type-Objekt für einen Typ abzurufen. Ein Ausdruckstyp hat die folgende Form:
In diesem Beispiel wird mithilfe der GetType-Methode der Typ ermittelt, der das Ergebnis einer numerischen Berechnung enthält. Dies hängt von den Speicheranforderungen der resultierenden Anzahl ab.
quelle
quelle
Sie können den Operator "typeof ()" in C # verwenden, müssen jedoch den Namespace mit System.IO aufrufen. Sie müssen das Schlüsselwort "is" verwenden, wenn Sie nach einem Typ suchen möchten.
quelle
typeof
ist nicht in einem Namespace definiert, sondern ein Schlüsselwort.System.IO
hat damit nichts zu tun.Leistungstest typeof () vs GetType ():
Ergebnisse im Debug-Modus:
Ergebnisse im Release-Modus:
quelle
DateTime
sollte es nicht verwendet werden, wenn Sie sich Sorgen über Zeiten unter 100 ms machen , da es den Zeitrahmen des Betriebssystems verwendet. Im Vergleich zuStopwatch
, der die ProzessorenTick
verwendet,DateTime
beträgt die von a in Win7 verwendete Auflösung 15 ms.