Réponses:
Cela devrait répondre à cette question, et plus encore.
La deuxième ligne, if (obj.GetType() == typeof(ClassA)) {}
est plus rapide, pour ceux qui ne veulent pas lire l'article.
(Sachez qu'ils ne font pas la même chose)
typeof(string).TypeHandle
avec l' ldtoken
instruction CIL, mais il semble que le CLR s'en occupe dans le JIT. Il faut encore quelques opcodes supplémentaires mais c'est une application plus généralisée de l'optimisation.
GetType
, is
est toujours un choix plus sûr en ce qui concerne les performances. Bien sûr, ils font des choses différentes.
object obj;
variable, n'est-elle pas déjà encadrée lorsque cela a tendance à être testé? Y a-t-il un cas où vous devez tester le type de quelque chose et qu'il n'est pas déjà encadré en tant qu'objet?
Est-ce que ce qui est le plus rapide importe, s'ils ne font pas la même chose? Comparer les performances d'énoncés ayant une signification différente semble être une mauvaise idée.
is
vous indique si l'objet implémente ClassA
n'importe où dans son héritage de type. GetType()
vous indique le type le plus dérivé.
Pas la même chose.
Ils ne font pas la même chose. Le premier fonctionne si obj est de type ClassA ou d'une sous-classe de ClassA. Le second ne correspondra qu'aux objets de type ClassA. Le second sera plus rapide car il n'a pas besoin de vérifier la hiérarchie des classes.
Pour ceux qui veulent connaître la raison, mais ne veulent pas lire l'article référencé dans est vs typeof .
J'ai fait des analyses comparatives là où ils font la même chose - des types scellés.
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());
Les fonctions génériques à tester pour les types génériques:
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;
}
J'ai également essayé des types personnalisés et les résultats étaient cohérents:
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());
Et les types:
sealed class Class1 { }
sealed class Class2 { }
struct Struct1 { }
struct Struct2 { }
Inférence:
L'appel GetType
sur struct
s est plus lent. GetType
est défini sur une object
classe qui ne peut pas être remplacée dans les sous-types et donc les struct
s doivent être encadrés pour être appelés GetType
.
Sur une instance d'objet, GetType
c'est plus rapide, mais très marginalement.
Sur le type générique, si T
c'est le cas class
, alors is
c'est beaucoup plus rapide. Si T
c'est le cas struct
, alors is
c'est beaucoup plus rapide que GetType
mais typeof(T)
c'est beaucoup plus rapide que les deux. En cas d' T
être class
, typeof(T)
n'est pas fiable car il est différent du type sous-jacent réel t.GetType
.
En bref, si vous avez une object
instance, utilisez GetType
. Si vous avez un class
type générique , utilisez is
. Si vous avez un struct
type générique , utilisez typeof(T)
. Si vous ne savez pas si le type générique est un type référence ou un type valeur, utilisez is
. Si vous voulez toujours être cohérent avec un style (pour les types scellés), utilisez is
..