1644 votes

Vérification de type : typeof, GetType, ou est ?

J’ai vu beaucoup de gens utiliser le code suivant :

Mais je sais que vous pourriez également faire ceci :

Ou ceci :

Personnellement, je pense que le dernier d'entre eux est la plus propre, mais y a-t-il quelque chose qui que me manque ? Quel est le meilleur à utiliser, ou est-ce vos préférences personnelles ?

1998voto

Jimmy Points 35501

Tous sont différents.

  • typeof prend un nom de type (que vous spécifiez au moment de la compilation).
  • GetType devient le moteur d'exécution type de l'instance.
  • is renvoie la valeur true si une instance est dans l'arbre d'héritage.

Exemple

class Animal { } 
class Dog : Animal { }

void PrintTypes(Animal a) { 
    print(a.GetType() == typeof(Animal)) // false 
    print(a is Animal)                   // true 
    print(a.GetType() == typeof(Dog))    // true
}

Dog spot = new Dog(); 
PrintTypes(spot);

Qu'en typeof(T)? Il est également résolu au moment de la compilation?

Oui. T est toujours ce que le type de l'expression est. Rappelez-vous, une méthode générique est fondamentalement un tas de méthodes avec le type approprié. Exemple:

string Foo<T>(T object) { return typeof(T).Name; }

Animal probably_a_dog = new Dog();
Dog    definitely_a_dog = new Dog();

Foo(probably_a_dog); // this calls Foo<Animal> and returns "Animal"
Foo<Animal>(probably_a_dog); // this is exactly the same as above
Foo<Dog>(probably_a_dog); // !!! This will not compile. The parameter expects a Dog, you cannot pass in an Animal.

Foo(definitely_a_dog); // this calls Foo<Dog> and returns "Dog"
Foo<Dog>(definitely_a_dog); // this is exactly the same as above.
Foo<Animal>(definitely_a_dog); // this calls Foo<Animal> and returns "Animal". 
Foo((Animal)definitely_a_dog); // this does the same as above, returns "Animal"

212voto

Andrew Hare Points 159332

Utiliser typeof lorsque vous voulez obtenir le type au moment de la compilation. Utiliser GetType lorsque vous voulez obtenir le type au moment de l'exécution. Il existe rarement des cas d'utilisation is comme elle le fait un casting et, dans la plupart des cas, vous vous retrouvez casting de la variable de toute façon.

Il y a une quatrième option, vous n'avez pas considéré (surtout si vous allez jeter un objet pour le type que vous trouverez); c'est-à utiliser as.

Foo foo = obj as Foo;

if (foo != null)
    // your code here

Cette utilise uniquement un exprimés alors que cette approche:

if (obj is Foo)
    Foo foo = (Foo)obj;

nécessite deux.

78voto

Scott Langham Points 17447

1.

Type t = typeof(obj1);
if (t == typeof(int))

C'est illégal, parce que typeof ne fonctionne que sur les types, et pas sur les variables. Je suppose obj1 est une variable. Donc, de cette manière typeof est statique, et fait de son travail au moment de la compilation au lieu de l'exécution.

2.

if (obj1.GetType() == typeof(int))

Cela est vrai si obj1 est exactement le type int. Si obj1 dérive de type int, si la condition sera fausse.

3.

if (obj1 is int)

Cela est vrai si obj1 est un int, ou si elle découle d'une classe appelée int, ou si elle implémente une interface, appelée int.

55voto

P Daddy Points 14228
Type t = typeof(obj1);
if (t == typeof(int))
    // Some code here

C'est une erreur. L'opérateur typeof en C# ne peut prendre les noms de type, pas des objets.

if (obj1.GetType() == typeof(int))
    // Some code here

Cela fonctionne, mais peut-être pas comme vous le souhaiteriez. Pour les types de valeur, que vous ai montré ici, c'est acceptable, mais pour les types référence, il ne renvoie vrai si le type était exactement le même type, pas quelque chose d'autre dans la hiérarchie d'héritage. Par exemple:

class Animal{}
class Dog : Animal{}

static void Foo(){
    object o = new Dog();

    if(o.GetType() == typeof(Animal))
        Console.WriteLine("o is an animal");
    Console.WriteLine("o is something else");
}

Ce serait d'imprimer "o is something else", car le type d' o est Dog, pas Animal. Vous pouvez faire ce travail, cependant, si vous utilisez l' IsAssignableFrom méthode de Type classe.

if(typeof(Animal).IsAssignableFrom(o.GetType())) // note use of tested type
    Console.WriteLine("o is an animal");

Cette technique laisse tout de même un problème majeur, cependant. Si votre variable est null, l'appel à l' GetType() lèvera une exception NullReferenceException. Donc, pour le faire fonctionner correctement, vous devriez faire:

if(o != null && typeof(Animal).IsAssignableFrom(o.GetType()))
    Console.WriteLine("o is an animal");

Avec cela, vous avez l'équivalent comportement de l' is mot-clé. Par conséquent, si c'est le comportement que vous voulez, vous devez utiliser l' is mot-clé, qui est plus lisible et plus efficace.

if(o is Animal)
    Console.WriteLine("o is an animal");

Ce qui est peut-être encore mieux, cependant, est d'utiliser l' as mot-clé, si vous avez besoin de faire plus que de simplement vérifier que quelque chose est d'un certain type, mais aussi de l'utilisation que l'objet en tant que type.

Par exemple, ne pas faire ceci:

if(o is Animal)
    ((Animal)o).Speak();

Au lieu de cela, faire ceci:

Animal a = o as Animal;
if(a != null)
    a.Speak();

5voto

StriplingWarrior Points 56276

Je crois que le dernier d'entre eux aussi se penche sur l’héritage (p. ex. chien est Animal == true), quel est le meilleur dans la plupart des cas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X