Проверьте, наследует ли 'T' или реализует класс / интерфейс


есть ли способ проверить, наследует ли T / реализует класс / интерфейс?

private void MyGenericClass<T> ()
{
    if(T ... inherits or implements some class/interface
}
7 70

7 ответов:

есть метод под названием тип.IsAssignableFrom().

чтобы проверить, если T наследует/реализует Employee:

typeof(Employee).IsAssignableFrom(typeof(T));

если вы нацелены на .NET Core, метод переместился в TypeInfo:

typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).Ge‌​tTypeInfo())

вы можете использовать ограничения на класс.

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только когда-либо

  1. T и Employee представляют один и тот же тип; или,
  2. Employee наследует от T.

это может быть использование в некоторые case, но для исходного вопроса (и более распространенного использования), чтобы определить, когда 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;
}

результаты

baseclass - >baseclass

правда

child1 - >baseclass

ложные

baseclass - >child1

правда

child2 - >baseclass

ложные

baseclass - >child2

правда

nobase - >baseclass

ложные

baseclass - > nobase

ложные

и

  • FAIL: c1 = b1
  • b1 = c1
  • FAIL: c2 = b1
  • b1 = c2

Я считаю, что синтаксис: typeof(Employee).IsAssignableFrom(typeof(T));

хотя IsAssignableFrom является лучшим способом, как заявили другие, если вам нужно только проверить, наследует ли класс от другого,typeof(T).BaseType == typeof(SomeClass) тоже работа.