为什么使用子类实例化父类对象时仅能访问父类的属性与方法
问题底层逻辑讲解
先明确你描述的代码场景,示例如下:
// 父类定义 public class Parent { public int parentID { get; set; } } // 子类继承父类 public class Child : Parent { public string childId { get; set; } } // 主方法中的赋值逻辑 Parent parentObj = new Child();
你观察到的差异本质是C# 编译期类型校验规则 和 运行期实际对象存储结构的不同,分两部分说明:
编译期仅能访问Parent属性的原因
- C# 是静态强类型语言,编译器会只根据变量的声明类型做成员访问合法性校验。上述代码中
parentObj的声明类型是Parent,编译器只会允许访问Parent类中定义的成员,childId是子类Child新增的成员,不在Parent的成员列表中,直接访问parentObj.childId会触发编译报错。 - 这个规则的核心目的是保证类型安全:编译器无法提前预判某个
Parent类型的变量中存储的是Parent本身的实例,还是其他继承自Parent的子类实例,所以只会按声明的公共成员范围做校验,避免访问不存在的成员。
运行期能看到两个类属性的原因
- 赋值给
parentObj的实际对象是new Child()创建的Child类实例,这个对象在堆上分配内存时,会完整保留父类Parent的所有成员,再叠加子类Child新增的成员,整个对象的内存结构是完整的子类结构,不会因为被赋值给父类类型的变量,就裁剪掉子类的成员部分。 - 运行期调试、反射读取对象属性时,读取的是堆上实际存储的完整对象结构,所以你可以同时看到
parentID和childId两个属性。
如果需要在代码中访问子类的属性,可以通过显式类型转换实现,只要实际对象确实是Child类型,转换后即可正常访问子类成员:
if (parentObj is Child childObj) { Console.WriteLine(childObj.childId); // 可正常访问子类属性 }
内容的提问来源于stack exchange,提问作者Raju Ahmed
相关产品推荐
相关产品推荐

