C#中使用new关键字后,子类仍调用抽象父类方法的问题求助
问题根源与解决办法
核心问题出在你用了new关键字而不是override——new只是隐藏基类的方法,并没有真正重写它。当代码通过IConvertThings<T,S>接口或者AConvertThings<T,S>基类引用来调用方法时,CLR会绑定到基类的实现,只有当变量的编译时类型是子类本身时,才会触发new定义的方法。
修正步骤
修改抽象类,把方法标记为可重写
把抽象类里的方法加上virtual关键字,允许子类重写:public abstract class AConvertThings<T,S> : IConvertThings<T,S> { // 注意:不要用关键字object做参数名,改成obj public virtual Task<T> ConvertTo(S obj) { throw new NotImplementedException("该转换器不支持ConvertTo操作"); } public virtual Task<S> ConvertFrom(T obj) { throw new NotImplementedException("该转换器不支持ConvertFrom操作"); } }子类用override替代new
子类实现方法时,用override关键字重写,而不是new:public class UserToDtoConverter : AConvertThings<UserDto, User> { public override async Task<UserDto> ConvertTo(User obj) { // 你的异步转换逻辑 var dto = new UserDto(); // 比如从EF异步获取关联数据 dto.Roles = await _roleRepository.GetByUserIdAsync(obj.Id); return dto; } // 不重写ConvertFrom,调用时会触发基类的异常 }
额外优化方案(可选)
如果想彻底避免“默认抛出异常”的设计,可以拆分接口,遵循接口隔离原则:
// 单向转换接口:仅支持转成T public interface IConvertTo<T, S> { Task<T> ConvertTo(S obj); } // 单向转换接口:仅支持从T转出 public interface IConvertFrom<T, S> { Task<S> ConvertFrom(T obj); } // 双向转换接口:组合两个单向接口 public interface IConvertThings<T, S> : IConvertTo<T, S>, IConvertFrom<T, S> { }
这样单向转换器只需要实现对应的单个接口,不需要继承抽象类,代码更清晰,也能在编译期就避免调用未实现的方法。
为什么原来的new不行?
举个例子:当你写IConvertThings<UserDto, User> converter = new UserToDtoConverter()时,变量的编译时类型是IConvertThings<T,S>,CLR会找这个接口的实现——也就是抽象类AConvertThings里的ConvertTo方法。子类的new方法只是在子类类型下隐藏了基类方法,并没有替换接口的实现,所以运行时还是会触发基类的异常。而用override后,子类的方法会覆盖基类的实现,无论通过接口还是基类引用调用,都会指向子类的方法。
内容的提问来源于stack exchange,提问作者CDove
相关产品推荐
相关产品推荐

