Проверьте, наследует ли 'T' или реализует класс / интерфейс
есть ли способ проверить, наследует ли T / реализует класс / интерфейс?
private void MyGenericClass<T> ()
{
if(T ... inherits or implements some class/interface
}
7 ответов:
есть метод под названием тип.IsAssignableFrom().
чтобы проверить, если
T
наследует/реализуетEmployee
:typeof(Employee).IsAssignableFrom(typeof(T));
если вы нацелены на .NET Core, метод переместился в 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
.это может быть использование в некоторые case, но для исходного вопроса (и более распространенного использования), чтобы определить, когда
T
наследует и реализует некоторыеclass
/interface
использовать:typeof(Employee).IsAssignableFrom(typeof(T))
то, что все действительно означает:
typeof(BaseType).IsAssignableFrom(typeof(DerivedType)) // => true
потому что вы можете буквально назначен экземпляр a
DerivedType
к экземпляру aBaseType
: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; }
результаты
baseclass - >baseclass
правда
child1 - >baseclass
ложные
baseclass - >child1
правда
child2 - >baseclass
ложные
baseclass - >child2
правда
nobase - >baseclass
ложные
baseclass - > nobase
ложные
и
- FAIL: c1 = b1
- b1 = c1
- FAIL: c2 = b1
- b1 = c2