J'ai une méthode d'extension pour sécuriser les objets de casting, qui ressemble à ceci:
public static T SafeCastAs<T>(this object obj) {
if (obj == null)
return default(T);
// which one I should use?
// 1. IsAssignableFrom
if (typeof(T).IsAssignableFrom(obj.GetType()))
return (T)obj;
// 2. IsInstanceOfType
if (typeof(T).IsInstanceOfType(obj))
return (T) obj;
// 3. is operator
if (obj is T)
return (T) obj;
return default(T);
}
Comme vous pouvez le voir, j'ai 3 choix, alors lequel devrais-je utiliser? En fait, quelle est la différence entre l'opérateur IsAssignableFrom
, IsInstanceOfType
et is
?
Vous utilisez ce que vous avez l'information pour.
Si vous souhaitez vérifier une instance et un type statique, utilisez is
.
Si vous n'avez pas le type statique, vous avez juste un objet Type
, mais vous voulez vérifier une instance, utilisez IsInstanceOfType
.
Si vous ne possédez pas d'instance et que vous souhaitez simplement vérifier la compatibilité entre une instance théorique de Type
et une autre Type
, utilisez IsAssignableFrom
.
Mais en réalité, il semble que vous réimplémentiez simplement l'opérateur as (sauf que le vôtre fonctionnerait également pour les types de valeur non nullables, ce qui n'est généralement pas une grosse limitation).
J'imagine que vous implémentez effectivement une version de l'opérateur as
qui fonctionne avec les types de valeur ainsi que les types de référence.
J'irais pour:
public static T SafeCastAs<T>(this object obj)
{
return (obj is T) ? (T) obj : default(T);
}
IsAssignableFrom
fonctionne avec des types et is
fonctionne avec des instances. Ils vous donneront les mêmes résultats dans votre cas, vous devriez donc utiliser la version la plus simple, IMHO.
En ce qui concerne IsInstanceOfType
: Ceci est implémenté en termes de IsAssignableFrom
, il n'y aura donc aucune différence.
Vous pouvez le prouver en utilisant Reflector pour examiner la définition de IsInstanceOfType()
:
public virtual bool IsInstanceOfType(object o)
{
if (o == null)
{
return false;
}
return this.IsAssignableFrom(o.GetType());
}
Je suppose que vous devriez juste aller avec " comme " à la place de votre "SafeCastAs" personnalisé. Mais cela ne fonctionnera que pour les classes (pas les structures), donc si vous voulez utiliser cette méthode pour les structures aussi, je peux l’obtenir.
L'opérateur "is" vous donne fondamentalement la même chose que Type.IsAssignableFrom, de sorte que vous ne pouvez conserver que "est", il vérifie si vous pouvez convertir en toute sécurité obj en T, sans exception. Donc, cela couvrira les deux vérifications précédentes de votre méthode. Mais sachez que cela ne vérifie pas si vous pouvez affecter obj à T, à cause des conversions définies par l'utilisateur: explicit et implicite keywords.
Ces fonctions et opérateurs ont une signification différente. Si vous avez des objets, vous pouvez toujours obtenir des types. donc vous ne travaillez pas sur ce que vous avez, mais vous faites ce qui doit être fait.
Lorsque vous travaillez avec une hiérarchie de classes, les différences sont très claires.
Regardez l'exemple suivant
class ABase
{
}
class BSubclass : ABase
{
}
ABase aBaseObj = new ABase();
BSubclass bSubclassObj = new BSubclass();
ABase subObjInBaseRef = new BSubclass();
Différentes opérations donnent des résultats différents.
typeof(ABase).IsInstanceOfType(aBaseObj) = True
typeof(ABase).IsInstanceOfType(bSubclassObj) = True
typeof(ABase).IsInstanceOfType(bSubclassObj) = True
typeof(BSubclass).IsInstanceOfType(aBaseObj) = False
bSubclassObj is ABase = True
aBaseObj is BSubclass = False
subObjInBaseRef is BSubclass = True
subObjInBaseRef is BSubclass = True
typeof(ABase).IsAssignableFrom(typeof(BSubclass)) = True
typeof(BSubclass).IsAssignableFrom(typeof(ABase))= False
Dans le cas où aucune hiérarchie ne serait, tout aurait été pareil . Mais si vous travaillez avec une hiérarchie, IsAssignableFrom
, is et IsInstanceOfType
donnent des résultats différents.
Il y a plus de combinaisons possibles qui pourraient être essayées. Par exemple, vous pouvez introduire une classe C qui n’est en aucun cas liée aux classes existantes dans cet exemple.