Risposte:
Questo dovrebbe rispondere a quella domanda, e poi alcuni.
La seconda linea, if (obj.GetType() == typeof(ClassA)) {} è più veloce, per coloro che non vogliono leggere l'articolo.
(Ricorda che non fanno la stessa cosa)
typeof(string).TypeHandlecon l' ldtokenistruzione CIL, ma sembra che CLR se ne occupi in JIT. Richiede ancora alcuni codici operativi aggiuntivi ma è un'applicazione più generalizzata dell'ottimizzazione.
GetType, isè sempre una scelta più sicura per quanto riguarda le prestazioni. Ovviamente fanno cose diverse.
object obj;variabile, non è già inscatolata quando tende a essere testata? C'è un caso in cui è necessario testare il tipo di qualcosa e non è già inscatolato come oggetto?
Importa che è più veloce, se non fanno la stessa cosa? Confrontare le prestazioni delle dichiarazioni con significati diversi sembra una cattiva idea.
isti dice se l'oggetto si implementa ClassAovunque nel suo tipo di gerarchia. GetType()ti parla del tipo più derivato.
Non è la stessa cosa
Non fanno la stessa cosa. Il primo funziona se obj è di tipo ClassA o di qualche sottoclasse di ClassA. Il secondo corrisponderà solo agli oggetti di tipo ClassA. Il secondo sarà più veloce poiché non deve controllare la gerarchia di classi.
Per coloro che vogliono conoscere il motivo, ma non vogliono leggere l'articolo a cui si fa riferimento è vs typeof .
Ho fatto alcuni benchmarking in cui 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<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());
Le funzioni generiche per verificare i tipi generici:
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;
}
Ho provato anche per 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<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());
E i tipi:
sealed class Class1 { }
sealed class Class2 { }
struct Struct1 { }
struct Struct2 { }
Inferenza:
Chiamando GetTypeil structs è più lento. GetTypeè definito su una objectclasse che non può essere sovrascritta nei sottotipi e quindi structdeve essere inscatolata per essere chiamata GetType.
Su un'istanza di oggetto, GetTypeè più veloce, ma molto marginale.
Sul tipo generico, se lo Tè class, allora isè molto più veloce. Se lo Tè struct, allora isè molto più veloce di GetTypema typeof(T)è molto più veloce di entrambi. In casi di Tessere class, typeof(T)non è affidabile poiché è diverso dal tipo di base reale t.GetType.
In breve, se si dispone di objectun'istanza, utilizzare GetType. Se hai un classtipo generico , usa is. Se hai un structtipo generico , usa typeof(T). Se non si è sicuri che il tipo generico sia di tipo di riferimento o di valore, utilizzare is. Se vuoi essere sempre coerente con uno stile (per i tipi sigillati), usa is..