Есть ли способ проверить, наследует ли 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())
T inherits U
фактически переводится как typeof(T).IsAssignableFrom(typeof(U))
.
T
ограничен каким-то другим типом TOther
, а затем при выполнении typeof(T)
будет фактически оценивать, typeof(TOther)
а не тот тип, который T
вы фактически передали, и в этом случае typeof(SomeInterface).IsAssignableFrom(typeof(T))
произойдет сбой (при условии, TOther
что также не реализуется SomeInterface
), даже если ваш конкретный тип реализован SomeInterface
.
IsAssignableFrom
из TypeInfo
класса принимает только TypeInfo , поскольку это единственный аргумент, так что образец должен быть следующим:typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
Вы можете использовать ограничения для класса.
MyClass<T> where T : Employee
Взгляните на http://msdn.microsoft.com/en-us/library/d5x73970.aspx
Если вы хотите проверить во время компиляции: Ошибка, если if 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
, или ifc
представляет тип значения, а текущий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
потому что вы можете буквально назначить экземпляр 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;
}
базовый класс-> базовый класс
Правда
child1-> базовый класс
Ложь
базовый класс-> ребенок1
Правда
child2-> базовый класс
Ложь
базовый класс-> ребенок2
Правда
nobase-> базовый класс
Ложь
базовый класс-> nobase
Ложь
а также
- НЕИСПРАВНОСТЬ: c1 = b1
- b1 = c1
- НЕИСПРАВНОСТЬ: c2 = b1
- b1 = c2
Хотя IsAssignableFrom - лучший способ, как заявляли другие, если вам нужно только проверить, наследуется ли класс от другого, typeof(T).BaseType == typeof(SomeClass)
тоже выполняет свою работу.
SomeClass
является прямым производным от BaseClass
.
Альтернативные способы сказать , если объект o
наследует класс или реализует интерфейс для использования is
и as
операторов.
Если вы хотите знать, наследует ли объект класс или реализует интерфейс, is
оператор вернет логический результат:
bool isCompatibleType = (o is BaseType || o is IInterface);
Если вы хотите использовать унаследованный класс или реализованный интерфейс после теста, as
оператор выполнит безопасное преобразование, возвращая ссылку на унаследованный класс или реализованный интерфейс, если он совместим, или null, если он несовместим:
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.