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
}
Il existe une méthode appelée Type.IsAssignableFrom() .
Pour vérifier si T
hé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())
Notez que si vous voulez contraindre votre type T
pour implémenter une interface ou hériter d'une classe, vous devriez opter pour la réponse de @snajahi, qui utilise des vérifications au moment de la compilation pour cela et ressemble génériquement à une meilleure approche de ce problème.
Vous pouvez utiliser des contraintes sur la classe.
MyClass<T> where T : Employee
Jetez un coup d'œil à http://msdn.microsoft.com/en-us/library/d5x73970.aspx
Si vous voulez vérifier pendant la compilation : Erreur si si T
n'a PAS mettre en œuvre l'interface/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 vous aidera.
La syntaxe correcte est
typeof(Employee).IsAssignableFrom(typeof(T))
Valeur de retour :
true
sic
et le courantType
représentent le même type, ou si leType
se trouve dans la hiérarchie d'héritage dec
ou si le courantType
est uninterface
quec
met en œuvre, ou sic
est un paramètre de type générique et la valeur actuelle deType
représente l'une des contraintes dec
ou sic
représente un type de valeur et la valeur couranteType
représenteNullable<c>
(Nullable(Of c)
en Visual Basic).false
si aucune de ces conditions n'esttrue
ou sic
estnull
.
Si Employee IsAssignableFrom T
puis T
hérite de Employee
.
L'usage
typeof(T).IsAssignableFrom(typeof(Employee))
renvoie à true
seulement lorsque soit
T
y Employee
représentent le même type ; ou,Employee
hérite de T
.Il peut s'agir d'un usage prévu dans un peu de mais pour la question originale (et l'usage le plus courant), pour déterminer quand T
hérite ou implémente certains class
/ interface
utiliser :
typeof(Employee).IsAssignableFrom(typeof(T))
Ce que tout le monde veut vraiment dire, c'est :
typeof(BaseType).IsAssignableFrom(typeof(DerivedType)) // => true
parce que vous pouvez littéralement affecter de une instance d'un DerivedType
à une instance d'un 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 faire une idée :
(via LinqPad, d'où le HorizontalRun
y 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
Véritable
enfant1->baseclasse
Faux
baseclass->child1
Véritable
enfant2->baseclasse
Faux
baseclass->child2
Véritable
nobase->baseclass
Faux
baseclass->nobase
Faux
et
- ÉCHEC : c1 = b1
- b1 = c1
- ÉCHEC : c2 = b1
- b1 = c2
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.