检查'T'是不是继承或实现了一个类/接口
Posted
技术标签:
【中文标题】检查\'T\'是不是继承或实现了一个类/接口【英文标题】:Check if 'T' inherits or implements a class/interface检查'T'是否继承或实现了一个类/接口 【发布时间】:2012-05-29 21:47:44 【问题描述】:有没有办法测试 T 是否继承/实现了一个类/接口?
private void MyGenericClass<T> ()
if(T ... inherits or implements some class/interface
【问题讨论】:
这似乎有效......如果(typeof(TestClass).IsAssignableFrom(typeof(T))),有人可以证实我的怀疑吗?谢谢! 我绝对肯定这个答案被重复了很多次! Felix K 即使这个答案被重复了很多次,它也帮助了很多人很多次;)......就像我五分钟前:) 【参考方案1】:有一个方法叫做Type.IsAssignableFrom()。
检查T
是否继承/实现Employee
:
typeof(Employee).IsAssignableFrom(typeof(T));
如果您的目标是 .NET Core,则该方法已移至 TypeInfo:
typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
请注意,如果您想限制您的类型 T
以实现某个接口或从某个类继承,您应该选择@snajahi 的答案,它使用编译时检查,通常类似于解决此问题的更好方法.
【讨论】:
你应该用一个例子来更新你的答案,例如typeof(T).IsAssignableFrom(typeof(IMyInterface)) 未完成 nikeee;旧答案仍然存在。 :) 我花了几秒钟才弄清楚出了什么问题。无论如何,+1,.net 框架的又一个不错的功能。 其实你说的方式就是我前段时间的方式。我纠正了这个。请参阅以前的 cmets。T inherits U
实际上转换为 typeof(T).IsAssignableFrom(typeof(U))
。
虽然这几乎可行,但存在一个问题,如果 T
被限制为其他类型 TOther
,那么在执行时,typeof(T)
实际上将评估为 typeof(TOther)
而不是任何类型T
你实际上已经通过了,在这种情况下,typeof(SomeInterface).IsAssignableFrom(typeof(T))
将失败(假设 TOther
也没有实现 SomeInterface
),即使你的具体类型确实实现了 SomeInterface
。
在 .net core IsAssignableFrom
of TypeInfo
类中只接受 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
是c
实现的interface
,或者如果c
是泛型类型参数并且当前Type
表示c
的约束之一,或者如果c
表示一个值类型和当前Type
代表Nullable<c>
(在Visual Basic 中为Nullable(Of c)
)。false
如果这些条件都不是true
,或者如果c
是null
。
source
说明
如果Employee IsAssignableFrom T
则T
继承自Employee
。
用法
typeof(T).IsAssignableFrom(typeof(Employee))
返回true
仅
T
和Employee
代表同一类型;或者,
Employee
继承自 T
。
这可能是 some 情况下的预期用法,但对于原始问题(以及更常见的用法),要确定 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://***.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->基类
错误
基类->child1
是的
child2->基类
错误
基类->child2
是的
nobase->基类
错误
基类->nobase
错误
和
失败:c1 = b1 b1 = c1 失败:c2 = b1 b1 = c2
【讨论】:
【参考方案6】:我相信语法是:typeof(Employee).IsAssignableFrom(typeof(T));
【讨论】:
这是预期的语法。 +1【参考方案7】:虽然正如其他人所说,IsAssignableFrom 是最好的方法,但如果您只需要检查一个类是否从另一个类继承,typeof(T).BaseType == typeof(SomeClass)
也可以完成这项工作。
【讨论】:
除非SomeClass
不是直接从BaseClass
派生的,否则该方法有效。【参考方案8】:
判断对象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 的答案。
【讨论】:
以上是关于检查'T'是不是继承或实现了一个类/接口的主要内容,如果未能解决你的问题,请参考以下文章
接口是不是可继承接口? 抽象类是不是可实现(implements)接口? 抽象类是不是可继承实体类(concrete class)?