è contro typeof

Quale di questi pezzi di codice è più veloce?

if (obj is ClassA) {} if (obj.GetType() == typeof(ClassA)) {} 

Edit: Sono consapevole che non fanno la stessa cosa.

Questo dovrebbe rispondere a questa domanda, e poi alcuni.

La seconda riga, if (obj.GetType() == typeof(ClassA)) {} , è più veloce, per coloro che non vogliono leggere l’articolo.

Importa che è più veloce, se non fanno la stessa cosa? Confrontare l’esecuzione delle affermazioni con un significato diverso sembra una ctriggers idea.

ti dice se l’object implementa ClassA ovunque nel suo tipo gerarchia. GetType() ti dice del tipo più derivato.

Non è la stessa cosa

Non fanno la stessa cosa Il primo funziona se obj è di tipo ClassA o di qualche sottoclass di ClassA. Il secondo abbinerà solo oggetti di tipo ClassA. Il secondo sarà più veloce poiché non deve controllare la gerarchia delle classi.

Per coloro che vogliono conoscere il motivo, ma non vogliono leggere l’articolo di riferimento in è vs typeof .

Ho fatto un po ‘di benchmarking dove fanno lo stesso – tipi sigillati.

 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(c1); // ~178ms b = GetType2(c1); // ~94ms b = Is(c1); // ~70ms b = GetType1(c2); // ~178ms b = GetType2(c2); // ~96ms b = Is(c2); // ~65ms b = GetType1(oc1); // ~190ms b = Is(oc1); // ~69ms b = GetType1(oc2); // ~180ms b = Is(oc2); // ~64ms b = GetType1(s1); // ~230ms b = GetType2(s1); // ~75ms b = Is(s1); // ~136ms b = GetType1(s2); // ~238ms b = GetType2(s2); // ~69ms b = Is(s2); // ~142ms b = GetType1(os1); // ~178ms b = Is(os1); // ~69ms b = GetType1(os2); // ~178ms b = Is(os2); // ~69ms } sw.Stop(); MessageBox.Show(sw.Elapsed.TotalMilliseconds.ToString()); 

Le funzioni generiche da testare per i tipi generici:

 static bool GetType1(T t) { return t.GetType() == typeof(S); } static bool GetType2(T t) { return typeof(T) == typeof(S); } static bool Is(T t) { return t is S; } 

Ho provato anche per i tipi personalizzati e i risultati sono stati coerenti:

 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(c1); // ~178ms b = GetType2(c1); // ~98ms b = Is(c1); // ~78ms b = GetType1(c2); // ~178ms b = GetType2(c2); // ~96ms b = Is(c2); // ~69ms b = GetType1(oc1); // ~178ms b = Is(oc1); // ~69ms b = GetType1(oc2); // ~178ms b = Is(oc2); // ~69ms b = GetType1(s1); // ~272ms b = GetType2(s1); // ~140ms b = Is(s1); // ~163ms b = GetType1(s2); // ~272ms b = GetType2(s2); // ~140ms b = Is(s2); // ~163ms b = GetType1(os1); // ~178ms b = Is(os1); // ~64ms b = GetType1(os2); // ~178ms b = Is(os2); // ~64ms } sw.Stop(); MessageBox.Show(sw.Elapsed.TotalMilliseconds.ToString()); 

E i tipi:

 sealed class Class1 { } sealed class Class2 { } struct Struct1 { } struct Struct2 { } 

Inferenza:

  1. Chiamare GetType su struct s è più lento. GetType è definito sulla class object che non può essere sovrascritto nei sottotipi e quindi struct s deve essere inserito in una GetType per essere chiamato GetType .

  2. Su un’istanza dell’object, GetType è più veloce, ma molto marginalmente.

  3. Nel tipo generico, se T è di class , allora è molto più veloce. Se T è struct , allora is molto più veloce di GetType ma typeof(T) è molto più veloce di entrambi. In caso di class T , typeof(T) non è affidabile poiché è diverso dal tipo sottostante effettivo t.GetType .

In breve, se hai un’istanza di un object , usa GetType . Se si dispone di un tipo di class generico, utilizzare is . Se hai un tipo di struct generico, usa typeof(T) . Se non si è sicuri se il tipo generico è il tipo di riferimento o il tipo di valore, utilizzare is . Se vuoi essere coerente con uno stile sempre (per i tipi sigillati), l’uso is ..