如何在C#中限制泛型类型不实现指定接口?
如何在C#中约束泛型类型不实现特定接口?
C#本身不支持直接通过泛型约束的where子句排除特定接口或类型,也就是你期望的where TVehicle : not ITruck这种语法目前并不存在于C#的规范中。
你当前在构造函数中通过运行时检查来阻止非法类型的方案是可行的,但确实不够优雅,而且存在两个明显的问题:
- 错误只能在运行时被发现,无法提前在编译阶段拦截
- 每次创建
PrivateGarage实例都会重复执行检查逻辑
优化后的运行时检查方案
可以把检查逻辑移到静态构造函数中,这样每个泛型类型实例(比如PrivateGarage<Car>、PrivateGarage<Truck>)只会被检查一次,而不是每次创建对象都执行检查。同时修正原代码中类型判断的错误(typeof(TVehicle) is ITruck是错误的,因为typeof(TVehicle)返回的是Type类型,永远不会是ITruck的实例):
public class PrivateGarage<TVehicle> { static PrivateGarage() { if (typeof(ITruck).IsAssignableFrom(typeof(TVehicle))) { throw new InvalidOperationException($"类型 {typeof(TVehicle).Name} 实现了ITruck,不能用于PrivateGarage"); } } public PrivateGarage() { // 实例构造逻辑 } }
关于编译时检查的尝试
目前没有原生的编译时排除约束,但可以通过一些技巧模拟类似效果,不过实用性有限:
- 比如创建辅助静态类,利用方法重载的约束匹配逻辑,让非法类型在调用时绑定到会抛出异常的重载,但本质还是运行时触发,只是检查时机提前到了泛型类型首次使用时
- 或者定义一个标记接口
INotTruck,要求所有合法类型实现它,但这种方式需要你能控制所有可能的TVehicle类型,扩展性很差
总的来说,在当前C#版本下,静态构造函数中的运行时检查是最实用的替代方案。
内容的提问来源于stack exchange,提问作者Michele Bortot
相关产品推荐
相关产品推荐

