You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中使用new关键字后,子类仍调用抽象父类方法的问题求助

问题根源与解决办法

核心问题出在你用了new关键字而不是override——new只是隐藏基类的方法,并没有真正重写它。当代码通过IConvertThings<T,S>接口或者AConvertThings<T,S>基类引用来调用方法时,CLR会绑定到基类的实现,只有当变量的编译时类型是子类本身时,才会触发new定义的方法。

修正步骤

  1. 修改抽象类,把方法标记为可重写
    把抽象类里的方法加上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操作"); 
        }
    }
    
  2. 子类用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 08:17:44