Есть ли способ проверить, наследует ли 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.