Czy istnieje sposób na sprawdzenie, czy T dziedziczy / implementuje klasę / interfejs?
private void MyGenericClass<T> ()
{
if(T ... inherits or implements some class/interface
}
Czy istnieje sposób na sprawdzenie, czy T dziedziczy / implementuje klasę / interfejs?
private void MyGenericClass<T> ()
{
if(T ... inherits or implements some class/interface
}
Odpowiedzi:
Istnieje metoda o nazwie Type.IsAssignableFrom () .
Aby sprawdzić, czy Tdziedziczy / implementuje Employee:
typeof(Employee).IsAssignableFrom(typeof(T));
Jeśli kierujesz .NET Core, metoda została przeniesiona do TypeInfo:
typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
T inherits Ufaktycznie przekłada się na typeof(T).IsAssignableFrom(typeof(U)).
Tjest ograniczony do innego typu TOther, to po wykonaniu w typeof(T)rzeczywistości zostanie oszacowany, typeof(TOther)a nie typ T, który faktycznie przeszedłeś, iw takim przypadku typeof(SomeInterface).IsAssignableFrom(typeof(T))zakończy się niepowodzeniem (zakładając, TOtherże również nie implementuje SomeInterface), nawet jeśli twój konkretny typ zaimplementował SomeInterface.
IsAssignableFromz TypeInfoklasy przyjmuje tylko TypeInfo jak to tylko argumentu więc próbki powinny być następujące:typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
Możesz użyć ograniczeń w klasie.
MyClass<T> where T : Employee
Spójrz na http://msdn.microsoft.com/en-us/library/d5x73970.aspx
Jeśli chcesz sprawdzić podczas kompilacji: Błąd, jeśli T NIE implementuje żądanego interfejsu / klasy, możesz użyć następującego ograniczenia
public void MyRestrictedMethod<T>() where T : MyInterface1, MyInterface2, MySuperClass
{
//Code of my method here, clean without any check for type constraints.
}
Mam nadzieję że to pomogło.
Prawidłowa składnia to
typeof(Employee).IsAssignableFrom(typeof(T))
Wartość zwracana:
truejeślica prądTypereprezentują ten sam typ, lub jeśli obecnyTypejest w hierarchii dziedziczeniac, lub jeśli obecnyTypejestinterface, żecnarzędzia, czycto ogólny parametr typu i obecnyTypestanowi jedno z ograniczeńclub ifcreprezentuje typ wartości, a bieżącyTypereprezentujeNullable<c>(Nullable(Of c)w Visual Basic).falsejeśli żaden z tych warunków nie jest spełnionytruelub jeślictaknull.
Jeśli Employee IsAssignableFrom Tto Tdziedziczy z Employee.
Użycie
typeof(T).IsAssignableFrom(typeof(Employee))
zwraca true tylko wtedy, gdy albo
Ti Employeereprezentują ten sam typ; lub,Employeedziedziczy z T.Może to być zamierzone użycie w niektórych przypadkach, ale w przypadku pierwotnego pytania (i bardziej powszechnego użycia), aby określić, kiedy Tdziedziczy lub implementuje niektóre class/ interface, użyj:
typeof(Employee).IsAssignableFrom(typeof(T))
Wszyscy tak naprawdę mają na myśli:
typeof(BaseType).IsAssignableFrom(typeof(DerivedType)) // => true
ponieważ możesz dosłownie przypisać z instancji a DerivedTypedo instancji a BaseType:
DerivedType childInstance = new DerivedType();
BaseType parentInstance = childInstance; // okay, assigning base from derived
childInstance = (DerivedType) parentInstance; // not okay, assigning derived from base
gdy
public class BaseType {}
public class DerivedType : BaseType {}
I kilka konkretnych przykładów, jeśli masz problem ze zrozumieniem tego:
(przez LinqPad, stąd HorizontalRuni 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
Prawdziwe
child1-> baseclass
Fałszywy
baseclass-> child1
Prawdziwe
child2-> baseclass
Fałszywy
baseclass-> child2
Prawdziwe
nobase-> baseclass
Fałszywy
baseclass-> nobase
Fałszywy
i
- BŁĄD: c1 = b1
- b1 = c1
- BŁĄD: c2 = b1
- b1 = c2
Chociaż IsAssignableFrom jest najlepszym sposobem, jak powiedzieli inni, jeśli potrzebujesz tylko sprawdzić, czy klasa dziedziczy po innej, również typeof(T).BaseType == typeof(SomeClass)wykonuje zadanie.
SomeClassnie pochodzi bezpośrednio z BaseClass.
Alternatywnymi sposobami stwierdzenia, czy obiekt odziedziczy klasę lub implementuje interfejs, jest użycie isias operatorów .
Jeśli chcesz wiedzieć tylko, czy obiekt dziedziczy klasę lub implementuje interfejs, isoperator zwróci wynik boolowski:
bool isCompatibleType = (o is BaseType || o is IInterface);
Jeśli po teście chcesz użyć dziedziczonej klasy lub zaimplementowanego interfejsu, asoperator wykona bezpieczne rzutowanie, zwracając odwołanie do odziedziczonej klasy lub zaimplementowanego interfejsu, jeśli jest zgodny lub zerowy, jeśli nie jest zgodny:
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.
Jeśli masz tylko typ T, użyj odpowiedzi @ nikeee.