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).TypeHandlemit der ldtokenCIL-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, isist 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.
isteilt Ihnen mit, ob das Objekt ClassAirgendwo 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 GetTypevon structs ist langsamer. GetTypewird für eine objectKlasse definiert , die in Untertypen nicht überschrieben werden kann und daher structzum Aufrufen eingerahmt werden muss GetType.
Auf einer Objektinstanz GetTypeist schneller, aber sehr marginal.
Wenn dies beim generischen Typ der Fall Tist class, isist dies viel schneller. Wenn Tja struct, dann isist es viel schneller als, GetTypeaber typeof(T)viel schneller als beide. In Fällen von TWesen class, typeof(T)ist seit seiner verschiedenen nicht zuverlässig von den tatsächlichen zugrunde liegenden Typ t.GetType.
Kurz gesagt, wenn Sie eine objectInstanz haben, verwenden Sie GetType. Wenn Sie einen generischen classTyp haben, verwenden Sie is. Wenn Sie einen generischen structTyp 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..