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

C#继承场景下的对象内存分配问题

C#继承场景下的对象内存分配详解

嘿,这个问题问到点子上了——很多刚摸C#继承的开发者都会在这一块绕晕,我给你掰扯得明明白白~

先敲个核心结论:当你执行new Derived()的时候,堆上只会创建一个单一、完整的Derived对象,它包含了基类Base的所有基础结构(哪怕你的Base是空类),再加上Derived自己的成员——根本不存在“基对象”和“派生对象”相互独立或者谁包含谁的情况。

下面分别拆解两种引用场景:

1. Derived d = new Derived();

  • 堆内存:分配一块连续的内存区域,里面是完整的Derived实例。哪怕你的Base是空类,这块内存也会包含.NET对象必备的对象头(同步块索引、类型指针等基础信息),再加上Derived自定义的所有成员(如果有的话)。
  • 栈内存:d是一个引用变量,它存储的是堆上那个Derived对象的内存地址。因为d的类型是Derived,所以你可以直接通过它访问Derived的所有成员,以及继承自Base的成员。

2. Base b = new Derived();

  • 堆内存:和上面完全一模一样!还是那个完整的Derived对象,内存分配没有任何区别——不会因为引用类型是Base就只分配Base的部分。
  • 栈内存:b是一个Base类型的引用变量,它同样存储的是堆上那个Derived对象的地址。只不过编译器会根据b的类型做限制,你只能通过它访问Base中定义的成员(除非你显式做类型转换),但堆里的对象本身从头到尾都是完整的Derived实例。

额外补充:空基类为啥也占空间?

哪怕你的Base没有任何自定义成员,每个.NET对象在堆上都会有固定的对象头开销,用来存储对象的类型信息、同步状态等核心数据。所以new Base()也会分配一定的内存,而Derived对象就是在这个基础上,叠加自己的成员数据。

打个形象的比方:把Derived对象看成一个完整的快递盒,Base的部分是盒子的硬纸板框架,Derived的成员是盒子里装的东西——整个盒子是一个不可分割的整体,不存在两个分开的盒子。引用类型只是贴在盒子上的标签,标签的类型决定了你能直接打开盒子的哪个隔层,但盒子本身的内容从来没变过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:12:34