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

泛型函数参数的多态行为:为何调用FirstChild的Fun而非SecondChild?

为什么Test(child)调用的是FirstChild.Fun而不是SecondChild.Fun?

这事儿的核心在于两个关键点:new关键字的隐藏特性和泛型方法中虚拟方法的绑定逻辑,咱们一步步拆解:

1. new关键字是「隐藏」方法,不是「重写」

你在SecondChild里写的public new void Fun(),本质是隐藏了从FirstChild继承来的Fun方法,而不是重写它。这意味着:

  • 这个SecondChild.Fun是一个全新的方法,和父类的Fun没有多态关联;
  • 只有当你直接用SecondChild类型的变量调用Fun时,才会执行这个新方法;
  • 如果是通过父类(Parent或FirstChild)的引用调用Fun,CLR会完全忽略这个隐藏的方法,走原本的多态override链。

2. 泛型方法Test<T>的方法绑定逻辑

泛型方法Test<T>的约束是where T : Parent,所以编译器在处理entity.Fun()的时候,会基于Parent类的方法定义来做绑定——因为Parent.Fun是virtual的,所以这是一个虚拟调用(virtual call),而不是绑定到T类型的new方法。

当你调用Test(child)时,T被推断为SecondChild,但运行时的虚拟调用逻辑是这样的:

  1. CLR找到对象的实际类型(SecondChild);
  2. 检查这个类型是否重写了Parent.Fun——但SecondChild的Fun是用new定义的,没有重写父类的virtual方法;
  3. 于是往上找父类FirstChild,发现它重写了Parent.Fun,所以执行FirstChild.Fun的实现。

要是你直接写child.Fun(),就会输出In SecondChild,因为这是直接调用SecondChild的隐藏方法,不走虚拟调用链。

3. 有没有强制转换?

完全没有。泛型方法里的entity就是SecondChild类型,没有任何显式或隐式的类型转换。虚拟调用本身就是CLR通过对象的方法表动态查找正确实现的过程,和类型转换无关。

举个更直观的对比验证:

SecondChild child = new SecondChild();
child.Fun(); // 输出"In SecondChild"
Parent p = child;
p.Fun(); // 输出"In FirstChild"——和泛型方法的结果一致

内容的提问来源于stack exchange,提问作者Henry159

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:02:33