C#为何调用该重载而非更具体的重载?(与重写相关)
问题
父类包含抽象方法abstract bool Filter(EntityComponent entity),但子类中我更倾向于实现bool Filter(BaseComponent entity)(EntityComponent是BaseComponent的子类,且其他地方也会调用后者)。为避免栈溢出,我给参数加了强制转换:
protected override bool Filter(EntityComponent entity) => Filter((BaseComponent)entity); protected bool Filter(BaseComponent entity) { return (AllowBeavers && entity.GetComponentFast<BeaverSpec>()) || (AllowBots && entity.GetComponentFast<BotSpec>()); }
但Visual Studio提示可以移除强制转换,且移除后仍能调用正确的方法。我很困惑:为什么编译器会选择Filter(BaseComponent)而非更具体的重载?移除转换后为什么不会发生递归?
解答
这背后是C#的重载解析规则在起作用:
不会递归的核心原因:重载解析优先匹配“非重写方法”
当你在重写的Filter(EntityComponent)方法里直接写Filter(entity)时,编译器首先会在当前类的成员中查找匹配的方法。当前类里有两个候选:- 重写的
Filter(EntityComponent)(父类抽象方法的实现) - 你自定义的
Filter(BaseComponent)
C#规定,在当前类中,非重写的方法优先级高于重写的父类方法——重写方法本质上属于父类的方法签名,当前类自己定义的重载会被优先考虑。因此编译器会选择你写的Filter(BaseComponent),而非调用自身导致递归。
- 重写的
移除强制转换仍能匹配的原因
EntityComponent是BaseComponent的子类,entity可以隐式转换为BaseComponent类型。当编译器处理Filter(entity)时,即便存在参数类型更精确的Filter(EntityComponent)重载,但因为它是重写的父类方法,优先级低于当前类自定义的Filter(BaseComponent),所以会自动完成隐式转换,调用后者。
简言之:编译器在当前类中查找方法时,自定义的重载比重写父类的方法优先级更高,因此既不会触发递归,也不需要手动强制转换。
内容的提问来源于stack exchange,提问作者Luke Vo
相关产品推荐
相关产品推荐

