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”,问题出在方法绑定的规则上:
- 如果用
override重写父类的虚方法:- 调用
a.Show()时,会根据运行时类型(C)来找到重写的方法,所以a.Show()和c.Show()都会输出C类的内容,这就是C#多态的正常表现。
- 调用
- 如果用
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
相关产品推荐
相关产品推荐

