Pour vérifier si un type est une sous-classe d'un autre type en C #, c'est simple:
typeof (SubClass).IsSubclassOf(typeof (BaseClass)); // returns true
Cependant, cela échouera:
typeof (BaseClass).IsSubclassOf(typeof (BaseClass)); // returns false
Existe-t-il un moyen de vérifier si un type est une sous-classe OR de la classe de base elle-même, sans utiliser d'opérateur OR
ni de méthode d'extension?
Apparemment non.
Voici les options:
is
et as
Comme vous l'avez déjà constaté, cela ne fonctionnera pas si les deux types sont identiques, voici un exemple de programme LINQPad qui illustre:
void Main()
{
typeof(Derived).IsSubclassOf(typeof(Base)).Dump();
typeof(Base).IsSubclassOf(typeof(Base)).Dump();
}
public class Base { }
public class Derived : Base { }
Sortie:
True
False
Ce qui indique que Derived
est une sous-classe de Base
, mais que Base
n'est (évidemment) pas une sous-classe de lui-même.
Maintenant, cela répondra à votre question particulière, mais cela vous donnera également des faux positifs. Comme Eric Lippert l'a souligné dans les commentaires, bien que la méthode retourne bien True
pour les deux questions ci-dessus, elle retournera également True
pour celles-ci, ce que vous ne voulez probablement pas:
void Main()
{
typeof(Base).IsAssignableFrom(typeof(Derived)).Dump();
typeof(Base).IsAssignableFrom(typeof(Base)).Dump();
typeof(int[]).IsAssignableFrom(typeof(uint[])).Dump();
}
public class Base { }
public class Derived : Base { }
Ici vous obtenez le résultat suivant:
True
True
True
Le dernier True
indiquera, si la méthode uniquement répond à la question posée, que uint[]
hérite de int[]
ou qu'ils soient du même type, ce qui n'est clairement pas le cas.
Donc, IsAssignableFrom
n'est pas tout à fait correct non plus.
is
et as
Le "problème" avec is
et as
dans le contexte de votre question est qu’ils vous demanderont d’opérer sur les objets et d’écrire l’un des types directement dans le code et de ne pas travailler avec Type
objets.
En d'autres termes, cela ne compilera pas:
SubClass is BaseClass
^--+---^
|
+-- need object reference here
cela ne va pas non plus:
typeof(SubClass) is typeof(BaseClass)
^-------+-------^
|
+-- need type name here, not Type object
cela ne va pas non plus:
typeof(SubClass) is BaseClass
^------+-------^
|
+-- this returns a Type object, And "System.Type" does not
inherit from BaseClass
Bien que les méthodes ci-dessus répondent à vos besoins, la seule réponse correcte à votre question (selon moi) est que vous aurez besoin d'une vérification supplémentaire:
typeof(Derived).IsSubclassOf(typeof(Base)) || typeof(Derived) == typeof(Base);
ce qui bien sûr a plus de sens dans une méthode:
public bool IsSameOrSubclass(Type potentialBase, Type potentialDescendant)
{
return potentialDescendant.IsSubclassOf(potentialBase)
|| potentialDescendant == potentialBase;
}
typeof(BaseClass).IsAssignableFrom(unknownType);
Vous devriez essayer d'utiliser Type.IsAssignableFrom .
Si vous essayez de le faire dans un projet PCL Xamarin Forms, les solutions ci-dessus utilisant IsAssignableFrom
donnent une erreur:
Erreur: 'Type' ne contient pas de définition pour 'IsAssignableFrom' et aucune méthode d'extension 'IsAssignableFrom' acceptant un premier argument de type 'Type' n'a pu être trouvée (il vous manque une directive using ou une référence Assembly?)
parce que IsAssignableFrom
demande un objet TypeInfo
. Vous pouvez utiliser la méthode GetTypeInfo()
à partir de System.Reflection
:
typeof(BaseClass).GetTypeInfo().IsAssignableFrom(typeof(unknownType).GetTypeInfo())
Je poste cette réponse dans l'espoir que quelqu'un me dise si et pourquoi ce serait une mauvaise idée. Dans mon application, je souhaite vérifier une propriété de Type pour m'assurer qu'elle est bien typeof (A) ou typeof (B), où B est une classe dérivée de A. Donc, mon code:
public class A
{
}
public class B : A
{
}
public class MyClass
{
private Type _helperType;
public Type HelperType
{
get { return _helperType; }
set
{
var testInstance = (A)Activator.CreateInstance(value);
if (testInstance==null)
throw new InvalidCastException("HelperType must be derived from A");
_helperType = value;
}
}
}
Je sens que je pourrais être un peu naïf ici, donc tout commentaire serait le bienvenu.