实现动态泛型抽象类遇CS0310错误:SqlQueryDynamicGetCbmClients需非抽象且带无参构造
嘿,这个CS0310错误我之前也踩过坑,咱们先把问题拆明白,再针对你的场景给出解决方案~
先搞懂错误到底说啥
Severity Code Description Project File Line Suppression State Error CS0310 'SqlQueryDynamicGetCbmClients'必须是具有公共无参数构造函数的非抽象类型,才能在泛型类型或方法中用作参数'TSelf'。
简单说,你定义的泛型抽象类(或者调用的泛型方法)对TSelf这个泛型参数加了new()约束——意思是这个类型必须能通过new 类型()的方式实例化。但你的SqlQueryDynamicGetCbmClients不满足这个要求:要么它是个抽象类(抽象类没法直接new),要么它没有公开的无参数构造函数(比如你只写了带参数的构造,编译器不会自动给你生成无参的)。
针对你的场景的修复思路
你的目标是简化动态泛型抽象类,适配“子类的TParams不同但Result相同”的场景,那我们可以从三个方向调整:
思路1:删掉没必要的new()约束
如果你的泛型基类根本不需要直接实例化TSelf,那这个约束完全可以去掉。比如你原来的基类可能是这么写的:
public abstract class BaseDynamicQuery<TSelf, TParams, TResult> where TSelf : BaseDynamicQuery<TSelf, TParams, TResult>, new() { // ... 你的基类逻辑 }
直接把new()约束删掉就行:
public abstract class BaseDynamicQuery<TSelf, TParams, TResult> where TSelf : BaseDynamicQuery<TSelf, TParams, TResult> { // ... 调整后的逻辑 }
思路2:让SqlQueryDynamicGetCbmClients满足约束
如果你的基类逻辑必须依赖new()约束(比如要在基类里创建子类实例),那就要修改你的子类:
- 如果它是抽象类,改成非抽象类(只要符合你的设计初衷)
- 给它加一个公开的无参数构造函数。比如:
public class SqlQueryDynamicGetCbmClients : BaseDynamicQuery<SqlQueryDynamicGetCbmClients, ClientParams, CommonResult> { // 必须加这个公开无参构造 public SqlQueryDynamicGetCbmClients() { } // 你原来的带参数构造可以保留 public SqlQueryDynamicGetCbmClients(string connectionString) { // ... 你的初始化逻辑 } // ... 其他类逻辑 }
思路3:重构泛型设计,彻底避开这个约束
既然你的场景是“多个子类共享同一个Result类型,只是TParams不同”,那完全可以重构基类,去掉TSelf这个参数,让基类固定Result类型,子类只需要指定TParams:
// 基类:固定Result类型,子类只传TParams就行 public abstract class BaseDynamicQuery<TParams, TResult> { public abstract TResult Execute(TParams parameters); } // 你的子类:Params是ClientParams,Result是CommonResult public class SqlQueryDynamicGetCbmClients : BaseDynamicQuery<ClientParams, CommonResult> { public override CommonResult Execute(ClientParams parameters) { // ... 你的业务逻辑 } } // 其他同Result的子类,只需要换TParams public class AnotherCbmQuery : BaseDynamicQuery<OtherParams, CommonResult> { public override CommonResult Execute(OtherParams parameters) { // ... 对应的业务逻辑 } }
这种设计更贴合你的需求,还避免了TSelf带来的构造函数约束问题,代码也更简洁。
最后总结一下
先检查你的泛型基类是不是真的需要new()约束——不需要就直接删;需要的话就调整子类满足条件。如果能重构泛型设计去掉TSelf,那是最省心的,完全避开这个坑。
内容的提问来源于stack exchange,提问作者Eryk Hubert Siejka

