Убедитесь, что 'T' наследует или реализует класс/интерфейс
Есть ли способ проверить, действительно ли T наследует/реализует класс/интерфейс?
private void MyGenericClass<T> ()
{
if(T ... inherits or implements some class/interface
}
Ответы
Ответ 1
Существует метод, называемый Type.IsAssignableFrom().
Чтобы проверить, наследует ли T
/реализует Employee
:
typeof(Employee).IsAssignableFrom(typeof(T));
Если вы нацеливаете .NET Core, метод переместился в TypeInfo:
typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
Ответ 2
Вы можете использовать ограничения для класса.
MyClass<T> where T : Employee
Взгляните на http://msdn.microsoft.com/en-us/library/d5x73970.aspx
Ответ 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
только тогда, когда либо
-
T
и Employee
представляют один и тот же тип; или же, -
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.