C'è un modo per verificare se T eredita / implementa una classe / interfaccia?
private void MyGenericClass<T> ()
{
if(T ... inherits or implements some class/interface
}
C'è un modo per verificare se T eredita / implementa una classe / interfaccia?
private void MyGenericClass<T> ()
{
if(T ... inherits or implements some class/interface
}
Risposte:
C'è un metodo chiamato Type.IsAssignableFrom () .
Per verificare se Teredita / implementa Employee:
typeof(Employee).IsAssignableFrom(typeof(T));
Se stai prendendo di mira .NET Core, il metodo è stato spostato in TypeInfo:
typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
T inherits Usi traduce effettivamente in typeof(T).IsAssignableFrom(typeof(U)).
Tè vincolato a qualche altro tipo TOther, quindi quando viene eseguito, typeof(T)valuterà effettivamente typeof(TOther)e non qualunque tipo Ttu abbia effettivamente passato, e in quel caso typeof(SomeInterface).IsAssignableFrom(typeof(T))fallirà (supponendo TOtherche non lo implementa anche SomeInterface), anche se il tuo tipo concreto ha implementato SomeInterface.
IsAssignableFromdella TypeInfoclasse accetta solo TypeInfo come unico argomento, quindi l'esempio dovrebbe essere il seguente:typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
È possibile utilizzare vincoli sulla classe.
MyClass<T> where T : Employee
Dai un'occhiata a http://msdn.microsoft.com/en-us/library/d5x73970.aspx
Se si desidera controllare durante la compilazione: Errore se T NON implementa l'interfaccia / classe desiderata, è possibile utilizzare il seguente vincolo
public void MyRestrictedMethod<T>() where T : MyInterface1, MyInterface2, MySuperClass
{
//Code of my method here, clean without any check for type constraints.
}
Spero che aiuti.
La sintassi corretta è
typeof(Employee).IsAssignableFrom(typeof(T))
Valore di ritorno:
truesece la correnteTyperappresentano lo stesso tipo, o se la correnteTypeè nella gerarchia di ereditarietà dic, o se la correnteTypeè unainterfacechecimplementa, o secè un parametro di tipo generico e la correnteTyperappresenta uno dei vincoli dic, o secrappresenta un tipo di valore e la correnteTyperappresentaNullable<c>(Nullable(Of c)in Visual Basic).falsese nessuna di queste condizioni è presentetrueo se locènull.
Se Employee IsAssignableFrom Tpoi Teredita da Employee.
L'utilizzo
typeof(T).IsAssignableFrom(typeof(Employee))
ritorna true solo quando uno dei due
Te Employeerappresentano lo stesso tipo; o,Employeeeredita da T.Questo può essere un uso previsto in alcuni casi, ma per la domanda originale (e l'uso più comune), per determinare quando Teredita o implementa alcune class/ interface, usa:
typeof(Employee).IsAssignableFrom(typeof(T))
Quello che tutti vogliono veramente dire è:
typeof(BaseType).IsAssignableFrom(typeof(DerivedType)) // => true
perché puoi letteralmente assegnare da un'istanza di a DerivedTypea un'istanza di a BaseType:
DerivedType childInstance = new DerivedType();
BaseType parentInstance = childInstance; // okay, assigning base from derived
childInstance = (DerivedType) parentInstance; // not okay, assigning derived from base
quando
public class BaseType {}
public class DerivedType : BaseType {}
E alcuni esempi concreti se hai problemi a capirlo:
(tramite LinqPad, da cui HorizontalRune 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;
}
classe base-> classe base
Vero
child1-> baseclass
Falso
classe base-> figlio1
Vero
child2-> baseclass
Falso
classe base-> figlio2
Vero
nobase-> baseclass
Falso
baseclass-> nobase
Falso
e
- FAIL: c1 = b1
- b1 = c1
- FAIL: c2 = b1
- b1 = c2
Sebbene IsAssignableFrom sia il modo migliore come altri hanno affermato, se hai solo bisogno di controllare se una classe eredita da un'altra, typeof(T).BaseType == typeof(SomeClass)fa anche il lavoro.
SomeClassnon sia derivato direttamente da BaseClass.
Un modo alternativo per sapere se un oggetto oeredita una classe o implementa un'interfaccia consiste nell'usare gli operatori ise as.
Se vuoi solo sapere se un oggetto eredita una classe o implementa un'interfaccia, l' isoperatore restituirà un risultato booleano:
bool isCompatibleType = (o is BaseType || o is IInterface);
Se si desidera utilizzare la classe ereditata o l'interfaccia implementata dopo il test, l' asoperatore eseguirà un cast sicuro, restituendo un riferimento alla classe ereditata o all'interfaccia implementata se compatibile o null se non compatibile:
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.
Se hai solo il tipo T, usa la risposta di @ nikeee.