Подтвердить что ты не робот

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

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

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

Ответ 1

Существует метод, называемый Type.IsAssignableFrom().

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

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

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

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

Ответ 3

Если вы хотите проверить во время компиляции: Ошибка, если если T НЕ реализует желаемый интерфейс/класс, вы можете использовать следующее ограничение

public void MyRestrictedMethod<T>() where T : MyInterface1, MyInterface2, MySuperClass
{
    //Code of my method here, clean without any check for type constraints.
}

Надеюсь, это поможет.

Ответ 4

Правильный синтаксис

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

Документация

Возвращаемое значение: true если c и текущий Type представляют один и тот же тип, или если текущий Type находится в иерархии наследования c, или если текущий Type является interface который реализует c, или если c является параметром универсального типа и current 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

В некоторых случаях это может быть предполагаемое использование, но для исходного вопроса (и более распространенного использования), чтобы определить, когда T наследует или реализует некоторый class/interface, используйте:

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

Ответ 5

Что все на самом деле означает:

typeof(BaseType).IsAssignableFrom(typeof(DerivedType)) // => true

потому что вы можете буквально назначить из экземпляра DerivedType экземпляр 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

True

child1- > BaseClass

False

baseclass- > child1

True

child2- > BaseClass

False

baseclass- > child2

True

nobase- > BaseClass

False

baseclass- > nobase

False

и

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

Ответ 6

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

Ответ 7

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

Ответ 8

Альтернативные способы определить, наследует ли объект o класс или реализует интерфейс, - использовать операторы is и 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.