C# 修改基類List中某一元素的子類類型

描述:

基類:BaseClass

子類1:A

子類2:B

然后我有一個List<BaseClass>類型的鏈表:list,我先往list中添加了兩個元素:

第一個元素為A類型,第二個元素為B類型,

然后我想改變第一個元素類型由原來的A到B;

直接使用list.ElementAt(0)取出第一個元素a,然后new 了一個新的B對象,因為我以為a的引用和鏈表list的第一個位置list[0]的引用相同,實際上并不是這樣的。

如果不new新對象,改變a里面的屬性,會直接反饋到list[0]里面,但是new 了新對象的話,a和list[0]就不是同一個東西了;

內存部分分析:

1. 初始狀態(執行前)

var a = new A();      // 創建A實例
var b = new B();      // 創建B實例
var list = new List<BaseClass>();  // 創建列表實例

堆棧 (Stack) 內存:

地址    變量名    值 (堆地址)
0x1000  a        → 0x2000
0x1004  b        → 0x3000  
0x1008  list     → 0x4000

堆 (Heap) 內存:

地址      對象類型    數據
0x2000    A實例      {StrBase=null, StrA=null}
0x3000    B實例      {StrBase=null, StrB=null}  
0x4000    List實例   [容量=4, 元素數組地址=0x5000]
0x5000    數組       [0x2000, null, null, null] ← 第一個元素指向A實例

2. 添加元素后

list.Add(a);
list.Add(b);

堆棧 (Stack) 內存:(不變)

地址    變量名    值 (堆地址)
0x1000  a        → 0x2000
0x1004  b        → 0x3000  
0x1008  list     → 0x4000

堆 (Heap) 內存:

地址      對象類型    數據
0x2000    A實例      {StrBase=null, StrA=null}
0x3000    B實例      {StrBase=null, StrB=null}  
0x4000    List實例   [容量=4, 元素數組地址=0x5000, 計數=2]
0x5000    數組       [0x2000, 0x3000, null, null] ← 第一個指向A,第二個指向B

3. 獲取元素引用

var aa = list.ElementAt(0);

堆棧 (Stack) 內存:

地址    變量名    值 (堆地址)
0x1000  a        → 0x2000
0x1004  b        → 0x3000  
0x1008  list     → 0x4000
0x100C  aa       → 0x2000  ← 新的變量aa,指向A實例

堆 (Heap) 內存:(不變)

地址      對象類型    數據
0x2000    A實例      {StrBase=null, StrA=null}
0x3000    B實例      {StrBase=null, StrB=null}  
0x4000    List實例   [容量=4, 元素數組地址=0x5000, 計數=2]
0x5000    數組       [0x2000, 0x3000, null, null]

4. 關鍵操作:重新賦值

aa = new B();  // 創建新的B實例

堆棧 (Stack) 內存:

地址    變量名    值 (堆地址)
0x1000  a        → 0x2000
0x1004  b        → 0x3000  
0x1008  list     → 0x4000
0x100C  aa       → 0x6000  ← aa現在指向新的B實例!

堆 (Heap) 內存:

地址      對象類型    數據
0x2000    A實例      {StrBase=null, StrA=null}
0x3000    B實例      {StrBase=null, StrB=null}  
0x4000    List實例   [容量=4, 元素數組地址=0x5000, 計數=2]
0x5000    數組       [0x2000, 0x3000, null, null] ← 第一個元素仍然指向A實例!
0x6000    B實例      {StrBase=null, StrB=null}   ← 新創建的B實例

關鍵點說明

1. 引用類型的本質

  • 變量存儲在堆棧a,?b,?list,?aa?這些變量都存儲在堆棧中

  • 對象存儲在堆中:實際的A、B實例和List實例存儲在堆中

  • 變量存儲的是引用:堆棧中的變量存儲的是堆中對象的地址

2. 賦值操作的含義

aa = new B();

這條語句的實際作用是:

  1. 在堆中創建新的B實例(地址0x6000)

  2. 將堆棧中變量aa的值從0x2000改為0x6000

  3. 不影響列表內部數組中存儲的引用值

3. 正確的修改方式

如果要修改列表中的元素,應該:

// 方式1:直接修改列表元素
list[0] = new B();  // 這會修改數組[0]位置的引用// 方式2:通過引用修改
ref var elementRef = ref list[0];
elementRef = new B();

4. 內存變化對比

錯誤的方式(你的代碼):

堆棧: aa → 0x6000 (新B實例)
堆:   數組[0] → 0x2000 (原來的A實例) ← 未改變!

正確的方式:

堆棧: aa → 0x6000 (新B實例)  
堆:   數組[0] → 0x6000 (新B實例) ← 已改變!

總結

從堆棧內存的角度看:

  • aa = new B()?只改變了堆棧中變量aa存儲的地址值

  • 列表的內部數組存儲在堆中,其元素引用保持不變

  • 要修改列表內容,必須直接操作列表本身,而不是操作從列表獲取的臨時變量

測試代碼:

static void Main(string[] args)
{Console.WriteLine("Hello, World!");var a = new A();a.StrBase = "A";var b = new B();//var list = new List<BaseClass>();var list = new BaseClass[2];list[0]=a;list[1]=b;//list.Add(b);//var aa = list.ElementAt(0);var aa = list.FirstOrDefault(s => s.StrBase.Equals("A"));aa = new B();//aa.StrBase =" new B()";int c = 0;
}
public class A : BaseClass
{ 
public string StrA {  get; set; }
}
public class B : BaseClass
{
public string StrB {  get; set; }
}
public class BaseClass
{public string StrBase { get; set; }
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/95987.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/95987.shtml
英文地址,請注明出處:http://en.pswp.cn/web/95987.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于STM32智能陽臺監控系統

基于STM32智能陽臺監控系統&#xff08;程序&#xff0b;原理圖元件清單&#xff09;功能介紹具體功能&#xff1a;1.采用STM32作為主控芯片實現檢測和控制&#xff1b;2.通過光敏電阻采集光線&#xff0c;將當前光線值在LCD1602顯示&#xff0c;低于50%控制LED亮&#xff0c;高…

動態維護有效區間:滑動窗口

右指針不斷移動獲取解&#xff0c;左指針不斷移動縮小解范圍 左指針的意義非常重要&#xff0c;相當于一個標兵&#xff0c;不斷與這個標兵進行比較&#xff0c;如果符合要求&#xff0c;這左指針進行移動&#xff0c;并進行操作&#xff0c;如果不符合要求&#xff0c;則左指針…

嵌入式學習---(單片機)

1.UART的概念通用異步收發器&#xff0c;2個串口&#xff08;1個串口被用于ISP下載程序&#xff0c;1個串口被用于和主機之間的通信&#xff09;&#xff0c;RXD(接收信號線) TXD(發送信號線)2、單工、半雙工、全雙工概念對比維度單工&#xff08;Simplex&#xff09;半雙工&am…

基于單片機的寵物屋智能系統設計與實現(論文+源碼)

1設計思路本設計基于單片機的寵物屋智能系統核心是實現對寵物生活環境及狀態的智能管理。系統以單片機為中樞&#xff0c;連接紅外測溫傳感器&#xff0c;可實時精準捕捉寵物體溫變化&#xff0c;以便及時發現健康異常&#xff1b;水位檢測傳感器時刻監測飲用水余量&#xff0c…

【面試】Java基礎面試題

1. Java 基本數據類型有哪些&#xff1f;場景&#xff1a;面試官問「String 是不是基本類型&#xff1f;」答案要點&#xff1a;8 種基本類型&#xff1a;byte, short, int, long, float, double, char, boolean。String 是引用類型。追問鏈條&#xff1a;問&#xff1a;為什么…

PHP云課堂在線網課系統 多功能網校系統 在線教育系統源碼

內容目錄一、詳細介紹二、效果展示1.部分代碼2.效果圖展示三、學習資料下載一、詳細介紹 云課堂&#xff0c;依托騰訊云基礎服務架構&#xff0c;采用C擴展框架Phalcon開發&#xff0c; 系統功能 實現了點播、直播、專欄、會員、積分、秒殺、微聊等。 友情提示&#xff1a;…

GEM5學習(4): 運行全系統模式的ARM系統

詳細說明可以見官網 gem5: Extending gem5 for ARM 下載鏡像 mkdir -p cpu_tests/benchmarks/bin/arm cd cpu_tests/benchmarks/bin/arm wget dist.gem5.org/dist/v22-0/test-progs/cpu-tests/bin/arm/Bubblesort wget dist.gem5.org/dist/v22-0/test-progs/cpu-tests/bin/arm…

快捷:常見ocr學術數據集預處理版本匯總(適配mmocr)

快捷&#xff1a;常見ocr學術數據集預處理版本匯總&#xff08;適配mmocr&#xff09;快捷&#xff1a;常見ocr學術數據集預處理版本匯總&#xff08;適配mmocr&#xff09;狀態指標驗證快捷&#xff1a;常見ocr學術數據集預處理版本匯總&#xff08;適配mmocr&#xff09; 狀…

從抽象到實現:Elasticsearch數據類型及其底層Lucene數據結構的深度解析

第一部分&#xff1a;Lucene基礎&#xff1a;核心索引結構Elasticsearch的強大功能根植于其核心——Apache Lucene&#xff0c;一個高性能、功能完備的搜索引擎庫 1。要深入理解Elasticsearch如何處理各種數據類型&#xff0c;首先必須剖析構成Lucene索引的三個基本數據結構&am…

Claude Code核心功能操作指南

&#xff08;一&#xff09;核心交互面板&#xff1a;認識操作界面 登錄后進入 Claude Code 主界面&#xff0c;核心區域分為三部分&#xff0c;各模塊功能清晰&#xff1a;可以通過 注冊免費體驗。左側導航欄&#xff1a;包含 “新建任務”“歷史記錄”“收藏夾”“幫助中心”…

數據倉庫進化:Agent驅動數智化新范式

目錄 回顧&#xff1a;從 "人為中心" 的數倉&#xff0c;到大數據與云數倉的進化 AI Agent 成為數據的 "新用戶" Agentic Data Stack 如何打破低效與內耗 企業數智化的新范式 案例與趨勢展望 所有軟件都會被 Agent 改寫一遍 經過半個世紀的數據倉庫發…

什么是shellcode

好的&#xff0c;我們來詳細地解釋一下什么是 Shellcode。核心定義Shellcode 是一段精煉的、用作有效載荷&#xff08;Payload&#xff09; 的機器代碼。它之所以叫這個名字&#xff0c;是因為最初這類代碼的唯一目的就是啟動一個命令行 Shell&#xff08;例如 /bin/sh&#xf…

線性代數 | 行圖像 / 列圖像

注&#xff1a;本文為 “線性代數 | 行圖像 / 列圖像” 相關合輯。 圖片清晰度受引文原圖所限。 略作重排&#xff0c;未整理去重。 如有內容異常&#xff0c;請看原文。 MIT 線性代數筆記一 行圖像和列圖像 線性代數行圖像與列圖像解析 herosunly 已于 2022-01-25 15:34:26 …

Batch Normalization:深度學習中的“加速器”與“穩定器”

在深度學習的世界里&#xff0c;神經網絡的訓練常常充滿了挑戰。從復雜的梯度問題到漫長的收斂過程&#xff0c;每一個環節都可能成為阻礙我們前進的絆腳石。而今天&#xff0c;我們要深入探討的 BatchNormalizationBatch NormalizationBatchNormalization&#xff08;批量歸一…

軟考備考①

一、數值及其轉換和數據的表示1、數值及其轉換①任意進制到十進制以二進制為例&#xff0c;以小數點做分割&#xff0c;小數點以左從二的零次方開始&#xff0c;小數點以右從二的負一次方開始。②十進制到任意進制利用短除法③二進制到十六進制分為小數點前和小數點后&#xff…

小程序緩存數據字典

import { getDict } from /api/profile;const CACHE_KEY DICT_CACHE;let dictCache new Map();// 初始化時加載緩存const loadCache () > {const cache uni.getStorageSync(CACHE_KEY);if (cache) {dictCache new Map(JSON.parse(cache));}};// 保存緩存到Storageconst…

Java對象在內存中的布局詳解

1、Java 對象內存布局&#xff08;HotSpot 虛擬機&#xff09;在 ?HotSpot 虛擬機? 中&#xff0c;一個 Java 對象在堆內存中的存儲布局可以分為以下幾個部分&#xff1a;1、對象頭&#xff08;Object Header&#xff09;?對象頭是對象內存布局中最重要的部分之一&#xff0…

鉀元素:從基礎認知到多元應用與前沿探索

一、鉀元素的基礎認知1.1 鉀元素的發現歷程在人類歷史的長河中&#xff0c;鉀的化合物早早就進入了人們的視野&#xff0c;并在生活和生產中得到了應用。古代時期&#xff0c;人們就知曉草木灰里含有鉀草堿&#xff0c;即碳酸鉀 。在日常的洗滌活動中&#xff0c;碳酸鉀發揮了重…

JAiRouter 配置文件重構紀實 ——基于單一職責原則的模塊化拆分與內聚性提升

JAiRouter 配置文件重構紀實 ——基于單一職責原則的模塊化拆分與內聚性提升 文章目錄JAiRouter 配置文件重構紀實 ——基于單一職責原則的模塊化拆分與內聚性提升一、背景&#xff1a;單體 YAML 的“熵增”困境二、重構策略&#xff1a;高內聚、低耦合的模塊化方案2.1 拆分原則…

驚!printf 不往屏幕輸?都是 fd 在搞鬼!爆肝拆解 Linux 文件描述符 + 重定向底層,學會直接在終端橫著走

文 章 目 錄一、文 件1、基 礎 知 識2、C 文 件 接 口&#xff08;1&#xff09;代 碼 示 例&#xff08;2&#xff09;當 前 路 徑&#xff08;3&#xff09;文 件 權 限&#xff08;4&#xff09;w&#xff08;5&#xff09;a&#xff08;6&#xff09;三 個 輸 入 輸 出 流3…