Antworten:
Dies sollte diese und noch einige weitere Fragen beantworten.
Die zweite Zeile if (obj.GetType() == typeof(ClassA)) {}
ist schneller für diejenigen, die den Artikel nicht lesen möchten.
(Seien Sie sich bewusst, dass sie nicht dasselbe tun)
typeof(string).TypeHandle
mit der ldtoken
CIL-Anweisung kompiliert wurde , aber es sieht so aus, als würde sich die CLR in der JIT darum kümmern. Es werden noch einige zusätzliche Opcodes benötigt, aber es handelt sich um eine allgemeinere Anwendung der Optimierung.
GetType
, is
ist immer eine sicherere Wahl so weit wie Leistung angeht. Natürlich machen sie verschiedene Dinge.
object obj;
Variable testen , ist sie nicht bereits boxen, wenn dies tendenziell getestet wird? Gibt es einen Fall, in dem Sie den Typ von etwas testen müssen und es nicht bereits als Objekt verpackt ist?
Ist es wichtig, was schneller ist, wenn sie nicht dasselbe tun? Der Vergleich der Leistung von Aussagen mit unterschiedlicher Bedeutung scheint eine schlechte Idee zu sein.
is
teilt Ihnen mit, ob das Objekt ClassA
irgendwo in seiner Typ-Hierarchie implementiert ist. GetType()
informiert Sie über den am meisten abgeleiteten Typ.
Nicht dasselbe.
Sie machen nicht das Gleiche. Das erste funktioniert, wenn obj vom Typ ClassA oder einer Unterklasse von ClassA ist. Der zweite entspricht nur Objekten vom Typ ClassA. Der zweite ist schneller, da die Klassenhierarchie nicht überprüft werden muss.
Für diejenigen, die den Grund wissen möchten, aber den Artikel, auf den verwiesen wird, nicht lesen möchten ist vs typeof .
Ich habe ein Benchmarking durchgeführt, bei dem die gleichen versiegelten Typen verwendet werden.
var c1 = "";
var c2 = typeof(string);
object oc1 = c1;
object oc2 = c2;
var s1 = 0;
var s2 = '.';
object os1 = s1;
object os2 = s2;
bool b = false;
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
{
b = c1.GetType() == typeof(string); // ~60ms
b = c1 is string; // ~60ms
b = c2.GetType() == typeof(string); // ~60ms
b = c2 is string; // ~50ms
b = oc1.GetType() == typeof(string); // ~60ms
b = oc1 is string; // ~68ms
b = oc2.GetType() == typeof(string); // ~60ms
b = oc2 is string; // ~64ms
b = s1.GetType() == typeof(int); // ~130ms
b = s1 is int; // ~50ms
b = s2.GetType() == typeof(int); // ~140ms
b = s2 is int; // ~50ms
b = os1.GetType() == typeof(int); // ~60ms
b = os1 is int; // ~74ms
b = os2.GetType() == typeof(int); // ~60ms
b = os2 is int; // ~68ms
b = GetType1<string, string>(c1); // ~178ms
b = GetType2<string, string>(c1); // ~94ms
b = Is<string, string>(c1); // ~70ms
b = GetType1<string, Type>(c2); // ~178ms
b = GetType2<string, Type>(c2); // ~96ms
b = Is<string, Type>(c2); // ~65ms
b = GetType1<string, object>(oc1); // ~190ms
b = Is<string, object>(oc1); // ~69ms
b = GetType1<string, object>(oc2); // ~180ms
b = Is<string, object>(oc2); // ~64ms
b = GetType1<int, int>(s1); // ~230ms
b = GetType2<int, int>(s1); // ~75ms
b = Is<int, int>(s1); // ~136ms
b = GetType1<int, char>(s2); // ~238ms
b = GetType2<int, char>(s2); // ~69ms
b = Is<int, char>(s2); // ~142ms
b = GetType1<int, object>(os1); // ~178ms
b = Is<int, object>(os1); // ~69ms
b = GetType1<int, object>(os2); // ~178ms
b = Is<int, object>(os2); // ~69ms
}
sw.Stop();
MessageBox.Show(sw.Elapsed.TotalMilliseconds.ToString());
Die generischen Funktionen zum Testen auf generische Typen:
static bool GetType1<S, T>(T t)
{
return t.GetType() == typeof(S);
}
static bool GetType2<S, T>(T t)
{
return typeof(T) == typeof(S);
}
static bool Is<S, T>(T t)
{
return t is S;
}
Ich habe auch nach benutzerdefinierten Typen gesucht und die Ergebnisse waren konsistent:
var c1 = new Class1();
var c2 = new Class2();
object oc1 = c1;
object oc2 = c2;
var s1 = new Struct1();
var s2 = new Struct2();
object os1 = s1;
object os2 = s2;
bool b = false;
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
{
b = c1.GetType() == typeof(Class1); // ~60ms
b = c1 is Class1; // ~60ms
b = c2.GetType() == typeof(Class1); // ~60ms
b = c2 is Class1; // ~55ms
b = oc1.GetType() == typeof(Class1); // ~60ms
b = oc1 is Class1; // ~68ms
b = oc2.GetType() == typeof(Class1); // ~60ms
b = oc2 is Class1; // ~68ms
b = s1.GetType() == typeof(Struct1); // ~150ms
b = s1 is Struct1; // ~50ms
b = s2.GetType() == typeof(Struct1); // ~150ms
b = s2 is Struct1; // ~50ms
b = os1.GetType() == typeof(Struct1); // ~60ms
b = os1 is Struct1; // ~64ms
b = os2.GetType() == typeof(Struct1); // ~60ms
b = os2 is Struct1; // ~64ms
b = GetType1<Class1, Class1>(c1); // ~178ms
b = GetType2<Class1, Class1>(c1); // ~98ms
b = Is<Class1, Class1>(c1); // ~78ms
b = GetType1<Class1, Class2>(c2); // ~178ms
b = GetType2<Class1, Class2>(c2); // ~96ms
b = Is<Class1, Class2>(c2); // ~69ms
b = GetType1<Class1, object>(oc1); // ~178ms
b = Is<Class1, object>(oc1); // ~69ms
b = GetType1<Class1, object>(oc2); // ~178ms
b = Is<Class1, object>(oc2); // ~69ms
b = GetType1<Struct1, Struct1>(s1); // ~272ms
b = GetType2<Struct1, Struct1>(s1); // ~140ms
b = Is<Struct1, Struct1>(s1); // ~163ms
b = GetType1<Struct1, Struct2>(s2); // ~272ms
b = GetType2<Struct1, Struct2>(s2); // ~140ms
b = Is<Struct1, Struct2>(s2); // ~163ms
b = GetType1<Struct1, object>(os1); // ~178ms
b = Is<Struct1, object>(os1); // ~64ms
b = GetType1<Struct1, object>(os2); // ~178ms
b = Is<Struct1, object>(os2); // ~64ms
}
sw.Stop();
MessageBox.Show(sw.Elapsed.TotalMilliseconds.ToString());
Und die Typen:
sealed class Class1 { }
sealed class Class2 { }
struct Struct1 { }
struct Struct2 { }
Inferenz:
Das Aufrufen GetType
von struct
s ist langsamer. GetType
wird für eine object
Klasse definiert , die in Untertypen nicht überschrieben werden kann und daher struct
zum Aufrufen eingerahmt werden muss GetType
.
Auf einer Objektinstanz GetType
ist schneller, aber sehr marginal.
Wenn dies beim generischen Typ der Fall T
ist class
, is
ist dies viel schneller. Wenn T
ja struct
, dann is
ist es viel schneller als, GetType
aber typeof(T)
viel schneller als beide. In Fällen von T
Wesen class
, typeof(T)
ist seit seiner verschiedenen nicht zuverlässig von den tatsächlichen zugrunde liegenden Typ t.GetType
.
Kurz gesagt, wenn Sie eine object
Instanz haben, verwenden Sie GetType
. Wenn Sie einen generischen class
Typ haben, verwenden Sie is
. Wenn Sie einen generischen struct
Typ haben, verwenden Sie typeof(T)
. Wenn Sie sich nicht sicher sind, ob der generische Typ der Referenztyp oder der Werttyp ist, verwenden Sie is
. Wenn Sie immer mit einem Stil übereinstimmen möchten (für versiegelte Typen), verwenden Sie is
..