Чи є спосіб перевірити, чи успадковує / реалізує клас клас / інтерфейс?
private void MyGenericClass<T> ()
{
if(T ... inherits or implements some class/interface
}
Чи є спосіб перевірити, чи успадковує / реалізує клас клас / інтерфейс?
private void MyGenericClass<T> ()
{
if(T ... inherits or implements some class/interface
}
Відповіді:
Існує метод, який називається Type.IsAssignableFrom () .
Щоб перевірити, чи Tуспадковується / реалізується Employee:
typeof(Employee).IsAssignableFrom(typeof(T));
Якщо ви націлюєтесь на .NET Core, метод перемістився до TypeInfo:
typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
T inherits Uнасправді перекладається на typeof(T).IsAssignableFrom(typeof(U)).
Tобмежується якимось іншим типом TOther, тоді при виконанні typeof(T)фактично буде оцінюватися, typeof(TOther)а не будь-якому типу, який Tви насправді передали, і в такому випадку typeof(SomeInterface).IsAssignableFrom(typeof(T))не вдасться (припускаючи, що TOtherце також не реалізується SomeInterface), навіть якщо ваш конкретний тип реалізував SomeInterface.
IsAssignableFromз TypeInfoкласу приймає тільки TypeInfo , оскільки це єдиний аргумент, так що зразок повинен бути наступним:typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
Ви можете використовувати обмеження для класу.
MyClass<T> where T : Employee
Погляньте на http://msdn.microsoft.com/en-us/library/d5x73970.aspx
Якщо ви хочете перевірити під час компіляції: Помилка, якщо, якщо T НЕ реалізує бажаний інтерфейс / клас, ви можете використовувати наступне обмеження
public void MyRestrictedMethod<T>() where T : MyInterface1, MyInterface2, MySuperClass
{
//Code of my method here, clean without any check for type constraints.
}
Я сподіваюся, що це допоможе.
Правильний синтаксис -
typeof(Employee).IsAssignableFrom(typeof(T))
Значення, що повертається:
trueякщоcі токTypeє один і той же тип, або якщо струмTypeзнаходиться в ієрархії успадкуванняc, або якщо струмTypeє ,interfaceщоcзнаряддя, або якщоcце загальний параметр типу і токTypeє одним з обмеженьc, або якщоcпредставляє тип значення, а поточнийTypeпредставляєNullable<c>(Nullable(Of c)у Visual Basic).falseякщо жодна з цих умов не єtrue, або якщоcєnull.
Якщо Employee IsAssignableFrom Tтоді Tуспадковує від Employee.
Використання
typeof(T).IsAssignableFrom(typeof(Employee))
повертається true лише тоді, коли обидва
Tі Employeeпредставляють однотипні; або,Employeeуспадковує від T.Це може бути призначеним використанням у деяких випадках, але для вихідного запитання (і більш поширеного використання), щоб визначити, коли Tуспадковує або реалізує деякі class/ interface, використовуйте:
typeof(Employee).IsAssignableFrom(typeof(T))
Що насправді мають на увазі всі:
typeof(BaseType).IsAssignableFrom(typeof(DerivedType)) // => true
тому що ви можете буквально призначити з екземпляра a DerivedTypeекземпляру a BaseType:
DerivedType childInstance = new DerivedType();
BaseType parentInstance = childInstance; // okay, assigning base from derived
childInstance = (DerivedType) parentInstance; // not okay, assigning derived from base
коли
public class BaseType {}
public class DerivedType : BaseType {}
І кілька конкретних прикладів, якщо у вас виникають проблеми з обгортанням голови:
(через LinqPad, звідси HorizontalRunі 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;
}
базовий клас-> базовий клас
Правда
дитина1-> базовий клас
помилковий
базовий клас-> дитина1
Правда
дитина2-> базовий клас
помилковий
базовий клас-> дитина2
Правда
nobase-> baseclass
помилковий
baseclass-> nobase
помилковий
і
- ПОМИЛКА: c1 = b1
- b1 = c1
- ПОМИЛКА: c2 = b1
- b1 = c2
Хоча IsAssignableFrom - найкращий спосіб, як зазначали інші, якщо вам потрібно лише перевірити, чи клас успадковується від іншого, typeof(T).BaseType == typeof(SomeClass)це теж робить.
SomeClassбезпосередньо не походить від BaseClass.
Альтернативні способи визначити, чи об’єкт oуспадковує клас або реалізує інтерфейс, це використання операторів isand as.
Якщо ви хочете знати лише, чи об’єкт успадковує клас або реалізує інтерфейс, isоператор поверне логічний результат:
bool isCompatibleType = (o is BaseType || o is IInterface);
Якщо ви хочете використовувати успадкований клас або реалізований інтерфейс після тесту, asоператор виконає безпечний привід, повернувши посилання на успадкований клас або реалізований інтерфейс, якщо сумісний або нульовий, якщо не сумісний:
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.
Якщо у вас лише тип T, використовуйте відповідь @ nikeee.