C#中基类与派生类三类实例化场景的区别,重点解析obj1与obj2的差异
C# 三种基类/派生类实例化方式的差异
首先明确核心规则:C# 中每个对象都有两个关键类型:声明类型(变量定义时标注的类型,编译期确定)和实际实例类型(new 关键字后跟随的类型,运行时确定),二者的差异直接决定了成员访问权限和多态行为。
你给出的示例代码里三个实例的区别如下:
1. Shape obj1 = new Shape();
- 声明类型:
Shape,实际实例类型:Shape - 属于最常规的同类型实例化,你可以通过
obj1直接访问Shape类中定义的所有成员:Property1、Property2,无法访问Rectangle类的扩展成员。 - 运行时实际内存中就是
Shape的实例,不包含任何Rectangle类的扩展属性和方法。
2. Shape obj2 = new Rectangle();
- 声明类型:
Shape,实际实例类型:Rectangle - 这是典型的向上转型,是 C# 多态的基础用法。运行时内存中创建的是完整的
Rectangle实例,包含Shape的所有成员,也包含Rectangle自己定义的Property3。 - 受编译期的声明类型限制,你直接通过
obj2只能访问Shape类定义的Property1、Property2,直接写obj2.Property3会触发编译错误。如果要访问派生类成员,需要手动做向下转型:Rectangle rect = (Rectangle)obj2; // 转型不会报错,因为实际实例就是Rectangle Console.WriteLine(rect.Property3); // 可以正常访问
obj1 和 obj2 的核心差异
二者的声明类型都是 Shape,所以编译期允许访问的成员完全一致,但运行时的行为有本质区别:
- 如果你尝试把
obj1强转为Rectangle,运行时会抛出InvalidCastException异常,因为obj1的实际实例就是Shape,不属于Rectangle的子类实例- 如果
Shape类中定义了虚方法,且Rectangle类做了重写,调用同一个方法时二者的执行逻辑完全不同:obj1会执行Shape类的实现,obj2会执行Rectangle类重写后的实现,这就是多态的核心表现。
3. Rectangle obj3 = new Rectangle();
- 声明类型:
Rectangle,实际实例类型:Rectangle - 实例类型和声明类型完全匹配,你可以直接访问所有继承自
Shape的成员(Property1、Property2),也可以直接访问Rectangle自己定义的Property3,不需要任何转型操作。
内容的提问来源于stack exchange,提问作者Amin Zahedi
相关产品推荐
相关产品推荐

