Есть ли способ проверить, действительно ли T наследует/реализует класс/интерфейс?
private void MyGenericClass<T> ()
{
if(T ... inherits or implements some class/interface
}
Есть ли способ проверить, действительно ли T наследует/реализует класс/интерфейс?
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())
Вы можете использовать ограничения для класса.
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
является параметром универсального типа и currentType
представляет одно из ограничений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
потому что вы можете буквально назначить из экземпляра 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
Я считаю, что синтаксис: typeof(Employee).IsAssignableFrom(typeof(T));
Хотя IsAssignableFrom - лучший способ, как заявили другие, если вам нужно только проверить, наследует ли класс от другого, typeof(T).BaseType == typeof(SomeClass)
тоже выполняет задание.
Альтернативные способы определить, наследует ли объект 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.