C#子类方法能否使用父类方法参数的派生类型作为入参重写
解决方案
方案1:泛型基类实现(推荐)
这是最符合你需求的优雅实现,通过两层基类同时满足「强类型参数」和「统一存储调用」的需求:
基类定义
// 非泛型根基类,用于统一管理所有UI元素 abstract class UIElement { // 公共统一调用入口 public abstract void Update(UpdateArgs args); public class UpdateArgs { } } // 泛型中间基类,具体UI元素继承该类,指定自身参数类型 abstract class UIElement<TArgs> : UIElement where TArgs : UIElement.UpdateArgs { // 密封非泛型Update,统一做参数校验和类型转换 public sealed override void Update(UpdateArgs args) { if (args is not TArgs typedArgs) { throw new ArgumentException($"仅支持 {typeof(TArgs)} 类型的参数", nameof(args)); } Update(typedArgs); } // 子类只需重写该方法,直接拿到强类型参数 public abstract void Update(TArgs args); }
具体UI元素实现
// 进度条实现 class ProgressBar : UIElement<ProgressBar.UpdateArgs> { public override void Update(UpdateArgs args) { base.Update(args); // 直接访问强类型参数,无需手动转换 double fullness = args.fullness; } public class UpdateArgs : UIElement.UpdateArgs { public double fullness; } } // 按钮实现示例 class Button : UIElement<Button.UpdateArgs> { public override void Update(UpdateArgs args) { base.Update(args); bool isClickable = args.IsClickable; } public class UpdateArgs : UIElement.UpdateArgs { public bool IsClickable; } }
该方案优势:
- 编译期强制约束子类的参数类型必须继承自
UIElement.UpdateArgs,避免非法参数类型 - 子类无需编写重复的类型校验和转换代码,直接使用强类型参数
- 保留了非泛型根基类,可以将任意UI元素存入
List<UIElement>等统一集合,上层调用无需感知具体子类类型
方案2:手动类型转换(不推荐)
如果不想引入泛型,可以在子类重写方法时手动做类型转换,但是代码冗余度高,容易出错:
class ProgressBar : UIElement { public override void Update(UpdateArgs args) { base.Update(args); if (args is not ProgressBar.UpdateArgs typedArgs) { throw new ArgumentException("参数类型不匹配", nameof(args)); } double fullness = typedArgs.fullness; } public class UpdateArgs : UIElement.UpdateArgs { public double fullness; } }
关于嵌套类自动继承的问题
C#没有内置机制保证子类的嵌套类自动继承父类的同名嵌套类,所有嵌套类的继承关系都需要手动声明。不过方案1中的泛型约束已经可以在编译期完成继承关系校验,如果子类传入的参数类型没有继承UIElement.UpdateArgs,编译器会直接报错,完全可以满足你的需求。
内容的提问来源于stack exchange,提问作者Meeso
相关产品推荐
相关产品推荐

