Gibt es eine Möglichkeit zu testen, ob T eine Klasse / Schnittstelle erbt / implementiert?
private void MyGenericClass<T> ()
{
if(T ... inherits or implements some class/interface
}
Gibt es eine Möglichkeit zu testen, ob T eine Klasse / Schnittstelle erbt / implementiert?
private void MyGenericClass<T> ()
{
if(T ... inherits or implements some class/interface
}
Antworten:
Es gibt eine Methode namens Type.IsAssignableFrom () .
So überprüfen Sie, ob Terbt / implementiert Employee:
typeof(Employee).IsAssignableFrom(typeof(T));
Wenn Sie auf .NET Core abzielen, wurde die Methode nach TypeInfo verschoben:
typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
T inherits Uübersetzt tatsächlich zu typeof(T).IsAssignableFrom(typeof(U)).
Tes auf einen anderen Typ beschränkt ist TOther, bei der Ausführung typeof(T)tatsächlich der typeof(TOther)Typ ausgewertet wird und nicht der Typ, den TSie tatsächlich übergeben haben, und in diesem Fall typeof(SomeInterface).IsAssignableFrom(typeof(T))fehlschlägt (vorausgesetzt TOther, nicht implementiert SomeInterface). obwohl Ihr konkreter Typ implementiert hat SomeInterface.
IsAssignableFromder TypeInfoKlasse nur TypeInfo als einziges Argument, daher sollte das Beispiel das folgende sein:typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
Sie können Einschränkungen für die Klasse verwenden.
MyClass<T> where T : Employee
Schauen Sie sich http://msdn.microsoft.com/en-us/library/d5x73970.aspx an
Wenn Sie während der Kompilierung überprüfen möchten: Fehler, wenn die gewünschte Schnittstelle / Klasse T NICHT implementiert wird, können Sie die folgende Einschränkung verwenden
public void MyRestrictedMethod<T>() where T : MyInterface1, MyInterface2, MySuperClass
{
//Code of my method here, clean without any check for type constraints.
}
Ich hoffe das hilft.
Die richtige Syntax lautet
typeof(Employee).IsAssignableFrom(typeof(T))
Rückgabewert:
truewenn ,cund der StromTyperepräsentiert den gleichen Typen ist , oder wenn der StromTypeist in der Vererbungshierarchiec, oder wenn der StromTypeist ,interfacedasscWerkzeuge, oder wenncein generischer Typ - Parameter und der StromTypeist eine der Einschränkungencoder ifcrepräsentiert einen Werttyp und der aktuelleTyperepräsentiertNullable<c>(Nullable(Of c)in Visual Basic).falsewenn keine dieser Bedingungen erfüllttrueist oder wenn dies der Fallcistnull.
Wenn Employee IsAssignableFrom Tdann Terbt von Employee.
Die Verwendung
typeof(T).IsAssignableFrom(typeof(Employee))
Gibt true nur zurück, wenn einer der beiden
Tund Employeerepräsentieren den gleichen Typ; oder,Employeeerbt von T.Dies kann in einigen Fällen eine beabsichtigte Verwendung sein , aber für die ursprüngliche Frage (und die häufigere Verwendung), um zu bestimmen, wann Teinige class/ geerbt oder implementiert werden interface, verwenden Sie:
typeof(Employee).IsAssignableFrom(typeof(T))
Was jeder wirklich meint ist:
typeof(BaseType).IsAssignableFrom(typeof(DerivedType)) // => true
weil Sie buchstäblich von einer Instanz von a DerivedTypezu einer Instanz von a zuweisen können BaseType:
DerivedType childInstance = new DerivedType();
BaseType parentInstance = childInstance; // okay, assigning base from derived
childInstance = (DerivedType) parentInstance; // not okay, assigning derived from base
wann
public class BaseType {}
public class DerivedType : BaseType {}
Und einige konkrete Beispiele, wenn Sie Probleme haben, Ihren Kopf darum zu wickeln:
(über LinqPad, daher das HorizontalRunund 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;
}
Grundklasse-> Grundklasse
Wahr
child1-> Grundklasse
Falsch
Grundklasse-> Kind1
Wahr
child2-> Grundklasse
Falsch
Grundklasse-> Kind2
Wahr
nobase-> baseclass
Falsch
Grundklasse-> Nobase
Falsch
und
- FEHLER: c1 = b1
- b1 = c1
- FEHLER: c2 = b1
- b1 = c2
Obwohl IsAssignableFrom der beste Weg ist, wie andere angegeben haben, typeof(T).BaseType == typeof(SomeClass)erledigt der Job auch , wenn Sie nur überprüfen müssen, ob eine Klasse von einer anderen erbt .
SomeClasssei denn, es ist nicht direkt abgeleitet von BaseClass.
Alternative Möglichkeiten, um festzustellen, ob ein Objekt oeine Klasse erbt oder eine Schnittstelle implementiert, sind die Operatoren isund as.
Wenn Sie nur wissen möchten, ob ein Objekt eine Klasse erbt oder eine Schnittstelle implementiert, gibt der isOperator ein boolesches Ergebnis zurück:
bool isCompatibleType = (o is BaseType || o is IInterface);
Wenn Sie die geerbte Klasse oder die implementierte Schnittstelle nach Ihrem Test verwenden möchten, führt der asOperator eine sichere Umwandlung durch und gibt einen Verweis auf die geerbte Klasse oder die implementierte Schnittstelle zurück, falls kompatibel, oder null, wenn nicht kompatibel:
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.
Wenn Sie nur den Typ haben T, verwenden Sie die Antwort von @ nikeee.