Comment vérifier si le type de variable correspond au type stocké dans une variable

96
User u = new User();
Type t = typeof(User);

u is User -> returns true

u is t -> compilation error

Comment tester si une variable est d'un certain type de cette manière?

Karan
la source

Réponses:

194

Les autres réponses contiennent toutes des omissions importantes.

L' isopérateur ne vérifie pas si le type d'exécution de l'opérande est exactement le type donné; plutôt, il vérifie si le type d'exécution est compatible avec le type donné:

class Animal {}
class Tiger : Animal {}
...
object x = new Tiger();
bool b1 = x is Tiger; // true
bool b2 = x is Animal; // true also! Every tiger is an animal.

Mais la vérification de l' identité du type avec la réflexion vérifie l' identité , pas la compatibilité

bool b5 = x.GetType() == typeof(Tiger); // true
bool b6 = x.GetType() == typeof(Animal); // false! even though x is an animal

or with the type variable
bool b7 = t == typeof(Tiger); // true
bool b8 = t == typeof(Animal); // false! even though x is an 

Si ce n'est pas ce que vous voulez, alors vous voulez probablement IsAssignableFrom:

bool b9 = typeof(Tiger).IsAssignableFrom(x.GetType()); // true
bool b10 = typeof(Animal).IsAssignableFrom(x.GetType()); // true! A variable of type Animal may be assigned a Tiger.

or with the type variable
bool b11 = t.IsAssignableFrom(x.GetType()); // true
bool b12 = t.IsAssignableFrom(x.GetType()); // true! A 
Eric Lippert
la source
4
Bien que l'approche finale présentée ici fonctionne, elle est inutilement verbeuse. typeof(Animal).IsInstanceOfType(x)est plus court et plus simple que typeof(Animal).IsAssignableFrom(x.GetType());(et Resharper suggérera d'utiliser le premier si vous utilisez le second).
Mark Amery
CLARIFICATION: pour répondre à la question initiale, remplacer tpar typeof(Animal). Ainsi la forme améliorée de Mark devient t.IsInstanceOfType(x).
ToolmakerSteve
13

GetType()existe sur chaque type de cadre, car il est défini sur le objecttype de base . Ainsi, quel que soit le type lui-même, vous pouvez l'utiliser pour renvoyer le sous-jacentType

Donc, tout ce que vous avez à faire est:

u.GetType() == t
Dave Bish
la source
1
En fait, la réponse d'Eric est utile et tout, mais ne répond pas à la question réelle de savoir comment tester avec un type inconnu de la manière "u is t" décrite dans la question d'origine, et la vôtre le fait.
Daniel
@Daniel - Pas exactement. La réponse de Dave n'est correcte que si vous souhaitez exclure des sous-classes de t. La réponse d'Eric explique principalement ce qu'il faut faire; il manque juste une clarification pour savoir où mettre "t". J'ajouterai un commentaire ici.
ToolmakerSteve
10

Vous devez voir si le type de votre instance est égal au type de la classe. Pour obtenir le type de l'instance, utilisez la GetType()méthode:

 u.GetType().Equals(t);

ou

 u.GetType.Equals(typeof(User));

devrait le faire. Évidemment, vous pouvez utiliser '==' pour faire votre comparaison si vous préférez.

Sam Holder
la source
+1 Mais préférez le deuxième choix. u.GetType.Equals(typeof(User));
Omar
Une des raisons pour lesquelles cela est moins sûr que d'utiliser == - est que si GetType () retourne d'une manière ou d'une autre null, il sera renvoyé.
Dave Bish
1
@Fuex, ouais moi, je pense que cela rend le code plus facile à lire si le typeof est en ligne, c'est pourquoi je l'ai posté comme ça, même si dans l'exemple OPs, il a déjà une variable tqui contient le type.
Sam Holder
@DaveBish si GetType retournait null, alors je craindrais que beaucoup de choses commencent à se produire ... mais point pris, vous avez bien sûr raison
Sam Holder
@SamHolder Ouais - La seule situation dans laquelle cela se produirait, serait si quelqu'un surchargeait un type de base et foutait en quelque sorte l'implémentation. Ce serait bizarre, bien sûr.
Dave Bish
4

Afin de vérifier si un objet est compatible avec une variable de type donnée, au lieu d'écrire

u is t

tu devrais écrire

typeof(t).IsInstanceOfType(u)
Mantas Janulionis
la source
1
Quel est l'avantage de la syntaxe plus verbeuse par rapport à la syntaxe «u is t»?
Kyle Humfeld le
@KyleHumfeld Si vous aviez Tapez foo; Objet A; vous ne pouvez pas écrire "A is foo", mais vous pouvez écrire foo.isInstanceOfType (A)
Timur Nuriyasov