Type t = typeof(obj1);
if (t == typeof(int))
// Some code here
Ceci est une erreur. L'opérateur typeof en C # ne peut prendre que des noms de type, pas des objets.
if (obj1.GetType() == typeof(int))
// Some code here
Cela fonctionnera, mais peut-être pas comme prévu. Pour les types de valeur, comme vous l'avez montré ici, c'est acceptable, mais pour les types de référence, cela ne retournerait vrai que si le type était exactement le même type, pas autre chose 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");
}
Cela s'imprimerait "o is something else", car le type de oest Dognon Animal. Vous pouvez cependant faire ce travail si vous utilisez la IsAssignableFromméthode de la Typeclasse.
if(typeof(Animal).IsAssignableFrom(o.GetType())) // note use of tested type
Console.WriteLine("o is an animal");
Cette technique reste cependant un problème majeur. Si votre variable est nulle, l'appel à GetType()lèvera une exception NullReferenceException. Donc, pour le faire fonctionner correctement, vous feriez:
if(o != null && typeof(Animal).IsAssignableFrom(o.GetType()))
Console.WriteLine("o is an animal");
Avec cela, vous avez un comportement équivalent du ismot - clé. Par conséquent, si tel est le comportement que vous souhaitez, vous devez utiliser le ismot - clé, qui est plus lisible et plus efficace.
if(o is Animal)
Console.WriteLine("o is an animal");
Dans la plupart des cas, cependant, le ismot - clé n'est toujours pas ce que vous voulez vraiment, car il ne suffit généralement pas de savoir qu'un objet est d'un certain type. Habituellement, vous souhaitez réellement utiliser cet objet en tant qu'instance de ce type, ce qui nécessite également de le convertir. Et vous pouvez donc vous retrouver à écrire du code comme ceci:
if(o is Animal)
((Animal)o).Speak();
Mais cela oblige le CLR à vérifier le type de l'objet jusqu'à deux fois. Il le vérifiera une fois pour satisfaire l' isopérateur, et s'il os'agit bien d'un Animal, on le refait vérifier pour valider le cast.
Il est plus efficace de le faire à la place:
Animal a = o as Animal;
if(a != null)
a.Speak();
L' asopérateur est un transtypage qui ne lèvera pas d'exception s'il échoue, au lieu de cela null. De cette façon, le CLR vérifie le type de l'objet une seule fois, et après cela, nous avons juste besoin de faire une vérification nulle, ce qui est plus efficace.
Mais attention: beaucoup de gens tombent dans un piège avec as. Parce qu'il ne lève pas d'exceptions, certaines personnes le considèrent comme un casting "sûr", et ils l'utilisent exclusivement, évitant les lancers réguliers. Cela conduit à des erreurs comme celle-ci:
(o as Animal).Speak();
Dans ce cas, le développeur suppose clairement que ce osera toujours un Animal, et tant que leur hypothèse est correcte, tout fonctionne bien. Mais s'ils se trompent, ce qu'ils obtiennent ici est un NullReferenceException. Avec un casting régulier, ils auraient obtenu un à la InvalidCastExceptionplace, ce qui aurait identifié plus correctement le problème.
Parfois, ce bug peut être difficile à trouver:
class Foo{
readonly Animal animal;
public Foo(object o){
animal = o as Animal;
}
public void Interact(){
animal.Speak();
}
}
C'est un autre cas où le développeur s'attend clairement oà être à Animalchaque fois, mais ce n'est pas évident dans le constructeur, où la asdistribution est utilisée. Ce n'est pas évident jusqu'à ce que vous arriviez à la Interactméthode, où le animalchamp devrait être attribué positivement. Dans ce cas, non seulement vous vous retrouvez avec une exception trompeuse, mais elle n'est levée que bien plus tard que lorsque l'erreur réelle s'est produite.
En résumé:
Si vous avez seulement besoin de savoir si un objet est d'un certain type, utilisez is.
Si vous devez traiter un objet comme une instance d'un certain type, mais vous ne savez pas avec certitude si l'objet sera de ce type, utilisez-le aset vérifiez-le null.
Si vous devez traiter un objet comme une instance d'un certain type, et que l'objet est censé être de ce type, utilisez une conversion régulière.
as!