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 T
erbt / 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))
.
T
es 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 T
Sie 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
.
IsAssignableFrom
der TypeInfo
Klasse 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:
true
wenn ,c
und der StromType
repräsentiert den gleichen Typen ist , oder wenn der StromType
ist in der Vererbungshierarchiec
, oder wenn der StromType
ist ,interface
dassc
Werkzeuge, oder wennc
ein generischer Typ - Parameter und der StromType
ist eine der Einschränkungenc
oder ifc
repräsentiert einen Werttyp und der aktuelleType
repräsentiertNullable<c>
(Nullable(Of c)
in Visual Basic).false
wenn keine dieser Bedingungen erfüllttrue
ist oder wenn dies der Fallc
istnull
.
Wenn Employee IsAssignableFrom T
dann T
erbt von Employee
.
Die Verwendung
typeof(T).IsAssignableFrom(typeof(Employee))
Gibt true
nur zurück, wenn einer der beiden
T
und Employee
repräsentieren den gleichen Typ; oder,Employee
erbt 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 T
einige 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 DerivedType
zu 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 HorizontalRun
und 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 .
SomeClass
sei denn, es ist nicht direkt abgeleitet von BaseClass
.
Alternative Möglichkeiten, um festzustellen, ob ein Objekt o
eine Klasse erbt oder eine Schnittstelle implementiert, sind die Operatoren is
und as
.
Wenn Sie nur wissen möchten, ob ein Objekt eine Klasse erbt oder eine Schnittstelle implementiert, gibt der is
Operator 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 as
Operator 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.