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

C#继承中父类引用指向子类实例,为何行为未匹配实际类型?

关于C#中a = c后类型与行为差异的解惑

嘿,这个问题戳中了C#面向对象里编译时类型和运行时类型的核心区别,咱们先把你没写完的代码补全(合理推测完整逻辑),再一步步拆解:

完整示例代码

class Program { 
    static void Main(string[] args) { 
        C c = new C(); 
        A a = new A(); 
        Console.WriteLine(a.GetType()); // 输出:A
        a = c; 
        Console.WriteLine(a.GetType()); // 输出:C
        a.Show(); 
        c.Show(); 
        Console.ReadLine(); 
    } 
} 
class A { 
    public virtual void Show() 
    {
        Console.WriteLine("我是A类的Show方法");
    }
}

class C : A
{
    // 两种写法会导致完全不同的行为,这就是你疑惑的根源!
    // 写法1:重写虚方法(override)
    public override void Show()
    {
        Console.WriteLine("我是C类的Show方法");
    }

    // 写法2:隐藏父类方法(new)
    // public new void Show()
    // {
    //     Console.WriteLine("我是C类的Show方法");
    // }
}

核心概念拆解

你看到a.GetType()返回C,这是因为GetType()返回的是对象的真实运行时类型——内存里实际创建的是C对象,不管你用什么类型的引用来指向它,这个真实类型都不会变。

而你觉得“a的行为不像c”,问题出在方法绑定的规则上:

  1. 如果用override重写父类的虚方法:
    • 调用a.Show()时,会根据运行时类型(C)来找到重写的方法,所以a.Show()和c.Show()都会输出C类的内容,这就是C#多态的正常表现。
  2. 如果用new关键字隐藏父类方法:
    • 编译器会根据编译时类型来绑定方法:a的编译时类型是A,所以a.Show()会调用A类的Show;而c的编译时类型是C,所以c.Show()调用C类的Show。这时候就会出现你看到的“a指向c但行为不一样”的情况。

总结一下

当你执行a = c时,a只是一个“戴着A类型面具的C对象”:

  • 它的真实身份(运行时类型)永远是C,所以GetType()会返回C;
  • 它能调用的方法范围由A类型决定(编译时类型);
  • 具体调用哪个版本的方法,要看方法是否是虚方法且被重写:虚方法看真实类型,非虚/隐藏方法看编译时类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:57:15