J'ai vu beaucoup de gens utiliser le code suivant:
Type t = typeof(obj1);
if (t == typeof(int))
// Some code here
Mais je sais que tu peux aussi faire ça:
if (obj1.GetType() == typeof(int))
// Some code here
Ou ca:
if (obj1 is int)
// Some code here
Personnellement, je pense que le dernier est le plus propre, mais y a-t-il quelque chose qui me manque? Lequel est le meilleur à utiliser, ou est-ce une préférence personnelle?
as
!as
n'est pas vraiment la vérification de type si ...as
est certainement une forme de vérification de type, autant que possibleis
! Il utilise efficacementis
les coulisses et est utilisé partout dans MSDN dans les endroits où il améliore la propreté du code par rapport àis
. Au lieu de vérifier d'is
abord, un appel pouras
établir une variable typée prête à l'emploi: si elle est nulle, répondez de manière appropriée; sinon, continuez. Certainement quelque chose que j'ai vu et utilisé un peu.as
/is
(couvert dans stackoverflow.com/a/27813381/477420 ) en supposant que ses travaux sémantiques s'appliquent à votre cas.GetType
méthode à laquelle vous vous connectez estSystem.Reflection.Assembly
- une méthode complètement différente et non pertinente ici.Réponses:
Tous sont différents.
typeof
prend un nom de type (que vous spécifiez au moment de la compilation).GetType
obtient le type d'exécution d'une instance.is
renvoie true si une instance se trouve dans l'arbre d'héritage.Exemple
Oui. T est toujours le type de l'expression. N'oubliez pas qu'une méthode générique est essentiellement un tas de méthodes avec le type approprié. Exemple:
la source
new Dog().GetType() is Animal
renvoie false (et votre autre version également) car.GetType()
retourne un objet de typeType
, etType
n'est pas unAnimal
.À utiliser
typeof
lorsque vous souhaitez obtenir le type au moment de la compilation . À utiliserGetType
lorsque vous souhaitez obtenir le type au moment de l'exécution . Il y a rarement des cas à utiliseris
car il fait un cast et, dans la plupart des cas, vous finissez par caster la variable de toute façon.Il y a une quatrième option que vous n'avez pas envisagée (surtout si vous allez également caster un objet avec le type que vous trouvez); c'est à utiliser
as
.Cela n'utilise qu'un seul cast
alors que cette approche:nécessite deux .Mise à jour (janvier 2020):
Exemple:
la source
is
effectue- t-il toujours un cast?typeof()
, et cette réponse ne suggère pas que vous pouvez. Vous passez le type à la place, c'est-à-dire quetypeof(string)
fonctionne,typeof("foo")
ne fonctionne pas.is
casting soit tel, une opération plutôt spéciale en IL.if (obj is Foo foo) { /* use foo here */ }
1.
Ceci est illégal, car
typeof
ne fonctionne que sur les types, pas sur les variables. Je suppose que obj1 est une variable. Ainsi, de cette manière, iltypeof
est statique et fait son travail au moment de la compilation au lieu de l'exécution.2.
C'est
true
siobj1
est exactement de typeint
. Siobj1
dérive deint
, la condition if serafalse
.3.
C'est
true
siobj1
est unint
, ou s'il dérive d'une classe appeléeint
, ou s'il implémente une interface appeléeint
.la source
Ceci est une erreur. L'opérateur typeof en C # ne peut prendre que des noms de type, pas des objets.
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:
Cela s'imprimerait
"o is something else"
, car le type deo
estDog
nonAnimal
. Vous pouvez cependant faire ce travail si vous utilisez laIsAssignableFrom
méthode de laType
classe.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:Avec cela, vous avez un comportement équivalent du
is
mot - clé. Par conséquent, si tel est le comportement que vous souhaitez, vous devez utiliser leis
mot - clé, qui est plus lisible et plus efficace.Dans la plupart des cas, cependant, le
is
mot - 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:Mais cela oblige le CLR à vérifier le type de l'objet jusqu'à deux fois. Il le vérifiera une fois pour satisfaire l'
is
opérateur, et s'ilo
s'agit bien d'unAnimal
, on le refait vérifier pour valider le cast.Il est plus efficace de le faire à la place:
L'
as
opérateur est un transtypage qui ne lèvera pas d'exception s'il échoue, au lieu de celanull
. 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:Dans ce cas, le développeur suppose clairement que ce
o
sera toujours unAnimal
, et tant que leur hypothèse est correcte, tout fonctionne bien. Mais s'ils se trompent, ce qu'ils obtiennent ici est unNullReferenceException
. Avec un casting régulier, ils auraient obtenu un à laInvalidCastException
place, ce qui aurait identifié plus correctement le problème.Parfois, ce bug peut être difficile à trouver:
C'est un autre cas où le développeur s'attend clairement
o
à être àAnimal
chaque fois, mais ce n'est pas évident dans le constructeur, où laas
distribution est utilisée. Ce n'est pas évident jusqu'à ce que vous arriviez à laInteract
méthode, où leanimal
champ 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
as
et vérifiez-lenull
.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.
la source
o is Animal
, ce qui nécessite que le CLR vérifie si le type de la variableo
est unAnimal
. La deuxième fois qu'il vérifie, c'est quand il transforme la déclaration((Animal)o).Speak()
. Plutôt que de vérifier deux fois, vérifiez une fois en utilisantas
.Si vous utilisez C # 7, il est temps de mettre à jour la grande réponse d'Andrew Hare. La correspondance de modèles a introduit un joli raccourci qui nous donne une variable typée dans le contexte de l'instruction if, sans nécessiter de déclaration / distribution distincte et de vérifier:
Cela semble assez décevant pour une distribution unique comme celle-ci, mais brille vraiment lorsque vous avez de nombreux types possibles dans votre routine. Ce qui suit est l'ancienne façon d'éviter de lancer deux fois:
Travailler autour de réduire autant que possible ce code, ainsi que d'éviter les doublons de cast du même objet m'a toujours dérangé. Ce qui précède est bien compressé avec un motif correspondant aux éléments suivants:
EDIT: mise à jour de la nouvelle méthode plus longue pour utiliser un commutateur selon le commentaire de Palec.
la source
switch
instruction avec correspondance de motifs est recommandée.if (obj1 is int integerValue) { integerValue++; }
J'avais une
Type
propriété à comparer et je ne pouvais pas utiliseris
(commemy_type is _BaseTypetoLookFor
), mais je pouvais les utiliser:Notez cela
IsInstanceOfType
etIsAssignableFrom
retourneztrue
lorsque vous comparez les mêmes types, où IsSubClassOf retournerafalse
. EtIsSubclassOf
ne fonctionne pas sur les interfaces, où les deux autres le font. (Voir aussi cette question et réponse .)la source
Je préfère est
Cela dit, si vous utilisez quels , vous risquez pas utiliser l' héritage correctement.
Supposons que cette personne: entité et cet animal: entité. Feed est une méthode virtuelle dans Entity (pour faire plaisir à Neil)
Plutôt
la source
Je crois que le dernier examine également l'héritage (par exemple, Dog is Animal == true), ce qui est mieux dans la plupart des cas.
la source
Cela dépend de ce que je fais. Si j'ai besoin d'une valeur booléenne (par exemple, pour déterminer si je vais transtyper en entier), je l'utilise
is
. Si j'ai besoin du type pour une raison quelconque (par exemple, pour passer à une autre méthode), je l'utiliseGetType()
.la source
Le dernier est plus propre, plus évident et vérifie également les sous-types. Les autres ne vérifient pas le polymorphisme.
la source
Utilisé pour obtenir l'objet System.Type pour un type. Une expression typeof prend la forme suivante:
Cet exemple utilise la méthode GetType pour déterminer le type utilisé pour contenir le résultat d'un calcul numérique. Cela dépend des exigences de stockage du nombre résultant.
la source
la source
Vous pouvez utiliser l'opérateur "typeof ()" en C # mais vous devez appeler l'espace de noms à l'aide de System.IO; Vous devez utiliser le mot clé "is" si vous souhaitez rechercher un type.
la source
typeof
n'est pas défini dans un espace de noms, c'est un mot-clé.System.IO
n'a rien à voir avec cela.Test de performance typeof () vs GetType ():
Résultats en mode débogage:
Résultats en mode release:
la source
DateTime
ne devrait pas être utilisé si vous êtes préoccupé par les temps ci - dessous 100ms , car il utilise le calendrier du système d' exploitation. Comparativement àStopwatch
, qui utilise les processeursTick
, la résolution utilisée par unDateTime
dans Win7 est une coqueluche de 15 ms.