Existe-t-il un moyen de tester si T hérite / implémente une classe / interface?
private void MyGenericClass<T> ()
{
if(T ... inherits or implements some class/interface
}
Existe-t-il un moyen de tester si T hérite / implémente une classe / interface?
private void MyGenericClass<T> ()
{
if(T ... inherits or implements some class/interface
}
Réponses:
Il existe une méthode appelée Type.IsAssignableFrom () .
Pour vérifier si Thérite / implémente Employee:
typeof(Employee).IsAssignableFrom(typeof(T));
Si vous ciblez .NET Core, la méthode a été déplacée vers TypeInfo:
typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
T inherits Use traduit en fait par typeof(T).IsAssignableFrom(typeof(U)).
Test contraint à un autre type TOther, puis lorsqu'il est exécuté, il typeof(T)sera en fait évalué à typeof(TOther)et non au type que Tvous avez réellement passé, et dans ce cas, typeof(SomeInterface).IsAssignableFrom(typeof(T))échouera (en supposant qu'il TOtherne soit pas également implémenté SomeInterface), même si votre type de béton a été implémenté SomeInterface.
IsAssignableFromde la TypeInfoclasse n'accepte que TypeInfo comme seul argument, donc l'exemple doit être le suivant:typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
Vous pouvez utiliser des contraintes sur la classe.
MyClass<T> where T : Employee
Jetez un œil à http://msdn.microsoft.com/en-us/library/d5x73970.aspx
Si vous souhaitez vérifier lors de la compilation: Erreur si si T n'implémente PAS l'interface / la classe souhaitée, vous pouvez utiliser la contrainte suivante
public void MyRestrictedMethod<T>() where T : MyInterface1, MyInterface2, MySuperClass
{
//Code of my method here, clean without any check for type constraints.
}
J'espère que cela aide.
La syntaxe correcte est
typeof(Employee).IsAssignableFrom(typeof(T))
Valeur de retour:
truesicet le courantTypereprésentent le même type, ou si le courantTypeest dans la hiérarchie d'héritage dec, ou si le courantTypeest uninterfacequicimplémente, ou sicest un paramètre de type générique et le courantTypereprésente l'une des contraintes dec, ou ifcreprésente un type valeur et le courantTypereprésenteNullable<c>(Nullable(Of c)dans Visual Basic).falsesi aucune de ces conditions ne l'esttrue, ou si elle l'cestnull.
Si Employee IsAssignableFrom Talors Thérite de Employee.
L'usage
typeof(T).IsAssignableFrom(typeof(Employee))
retourne true uniquement lorsque soit
Tet Employeereprésentent le même type; ou,Employeehérite de T.Cela peut être une utilisation prévue dans certains cas, mais pour la question d'origine (et l'utilisation la plus courante), pour déterminer quand Thérite ou implémente certains class/ interface, utilisez:
typeof(Employee).IsAssignableFrom(typeof(T))
Ce que tout le monde veut vraiment dire, c'est:
typeof(BaseType).IsAssignableFrom(typeof(DerivedType)) // => true
car vous pouvez littéralement attribuer d' une instance de a DerivedTypeà une instance de a BaseType:
DerivedType childInstance = new DerivedType();
BaseType parentInstance = childInstance; // okay, assigning base from derived
childInstance = (DerivedType) parentInstance; // not okay, assigning derived from base
quand
public class BaseType {}
public class DerivedType : BaseType {}
Et quelques exemples concrets si vous avez du mal à vous y mettre la tête:
(via LinqPad, d'où le HorizontalRunet Dump)
void Main()
{
// http://stackoverflow.com/questions/10718364/check-if-t-inherits-or-implements-a-class-interface
var b1 = new BaseClass1();
var c1 = new ChildClass1();
var c2 = new ChildClass2();
var nb = new nobase();
Util.HorizontalRun(
"baseclass->baseclass,child1->baseclass,baseclass->child1,child2->baseclass,baseclass->child2,nobase->baseclass,baseclass->nobase",
b1.IsAssignableFrom(typeof(BaseClass1)),
c1.IsAssignableFrom(typeof(BaseClass1)),
b1.IsAssignableFrom(typeof(ChildClass1)),
c2.IsAssignableFrom(typeof(BaseClass1)),
b1.IsAssignableFrom(typeof(ChildClass2)),
nb.IsAssignableFrom(typeof(BaseClass1)),
b1.IsAssignableFrom(typeof(nobase))
).Dump("Results");
var results = new List<string>();
string test;
test = "c1 = b1";
try {
c1 = (ChildClass1) b1;
results.Add(test);
} catch { results.Add("FAIL: " + test); }
test = "b1 = c1";
try {
b1 = c1;
results.Add(test);
} catch { results.Add("FAIL: " + test); }
test = "c2 = b1";
try {
c2 = (ChildClass2) b1;
results.Add(test);
} catch { results.Add("FAIL: " + test); }
test = "b1 = c2";
try {
b1 = c2;
results.Add(test);
} catch { results.Add("FAIL: " + test); }
results.Dump();
}
// Define other methods and classes here
public static class exts {
public static bool IsAssignableFrom<T>(this T entity, Type baseType) {
return typeof(T).IsAssignableFrom(baseType);
}
}
class BaseClass1 {
public int id;
}
class ChildClass1 : BaseClass1 {
public string name;
}
class ChildClass2 : ChildClass1 {
public string descr;
}
class nobase {
public int id;
public string name;
public string descr;
}
baseclass-> baseclass
Vrai
child1-> baseclass
Faux
baseclass-> enfant1
Vrai
child2-> baseclass
Faux
baseclass-> enfant2
Vrai
nobase-> baseclass
Faux
baseclass-> nobase
Faux
et
- ÉCHEC: c1 = b1
- b1 = c1
- ÉCHEC: c2 = b1
- b1 = c2
Bien que IsAssignableFrom soit le meilleur moyen, comme d'autres l'ont indiqué, si vous avez seulement besoin de vérifier si une classe hérite d'une autre, typeof(T).BaseType == typeof(SomeClass)fait également le travail.
SomeClassne soit directement dérivé de BaseClass.
Une autre façon de savoir si un objet ohérite d'une classe ou implémente une interface consiste à utiliser les opérateurs iset as.
Si vous voulez savoir uniquement si un objet hérite d'une classe ou implémente une interface, l' isopérateur renverra un résultat booléen:
bool isCompatibleType = (o is BaseType || o is IInterface);
Si vous souhaitez utiliser la classe héritée ou l'interface implémentée après votre test, l' asopérateur effectuera un cast sécurisé, renvoyant une référence à la classe héritée ou à l'interface implémentée si compatible ou null si non compatible:
BaseType b = o as BaseType; // Null if d does not inherit from BaseType.
IInterface i = o as IInterface; // Null if d does not implement IInterface.
Si vous n'avez que le type T, utilisez la réponse de @ nikeee.