【C#】關於字典存儲不同類型變數的效果

来源:https://www.cnblogs.com/misakacirno/archive/2020/06/25/13191553.html
-Advertisement-
Play Games

最近在寫一個小工具,裡面用到了一個自定義的類,並且需要對該類進行多個實例化。 因為需要根據需求來取不同的實例,所以決定將其放置到一個字典中,以便取用。 另外,由於可能之後會改動實例化時的內容,所以準備將具體實例化的代碼封裝到一個單獨的子程式中,以便更改。 所以寫瞭如下的代碼: 1 namespace ...


最近在寫一個小工具,裡面用到了一個自定義的類,並且需要對該類進行多個實例化。

因為需要根據需求來取不同的實例,所以決定將其放置到一個字典中,以便取用。

另外,由於可能之後會改動實例化時的內容,所以準備將具體實例化的代碼封裝到一個單獨的子程式中,以便更改。

 

所以寫瞭如下的代碼:

 1 namespace Example
 2 {
 3     public partial class MainWindow : Window
 4     {
 5         //因為在其他地方會引用到,所以放在最外層定義
 6         public static MyClass staff1; 
 7         public static MyClass staff2;
 8         public static Dictionary<string, MyClass> staffDic = new Dictionary<string, MyClass>()
 9         {
10             {"aaa",staff1},
11             {"bbb",staff2}
12         };
13 
14         private void Window_Loaded(object sender, RoutedEventArgs e)
15         {
16             InitializationStaff();
17             System.Console.WriteLine(staffDic["aaa"]);
18         }
19 
20         private void InitializationStaff() //給變數添加實例
21         {
22             staff1=new MyClass(){a=1,b=2,c=3};
23             staff2=new MyClass(){a=3,b=2,a=1};
24         }
25     }
26 
27     Class MyClass 
28     {
29         public int a;
30         public int b;
31         public int c;
32     }
33 }

結果發現,輸出的時候報錯了,提示在字典中該項對應的內容為Null。

而如果將代碼修改一下,在外面先實例化一下:

namespace Example
{
    public partial class MainWindow : Window
    {
        //因為在其他地方會引用到,所以放在最外層定義
        //在定義變數時就實例化
        public static MyClass staff1 = new MyClass(); 
        public static MyClass staff2 = new MyClass();
        public static Dictionary<string, MyClass> staffDic = new Dictionary<string, MyClass>()
        {
            {"aaa",staff1},
            {"bbb",staff2}
        };

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            InitializationStaff();
            System.Console.WriteLine(staffDic["aaa"]);
        }

        private void InitializationStaff() //給變數修改內容
        {
            staff1.a = 1;
            staff1.b = 2;
            staff1.c = 3;

            staff2.a = 3;
            staff2.b = 2;
            staff2.a = 1;
        }
    }

    Class MyClass 
    {
        public int a;
        public int b;
        public int c;
    }
}

此時,輸出的內容就正常了。

那麼究竟這背後發生了什麼呢?

 

在請教過朋友後瞭解到,在C#中,為字典添加key對應的value時,實際上發生的效果是將目標內容複製到字典中,而並非是引用

瞭解過變數和記憶體相關知識的人應該知道,當我們寫下一行代碼:

int a = 123;

此時發生的是,系統首先找到一塊記憶體空間,把123這個值存儲到其中,並記錄該記憶體空間的地址A。

而在變數a中,實際存儲的內容就是地址A。

 

當我們將變數添加至字典中時:

Dictionary<string, int> Dic = new Dictionary<string, int>() { { "number1", a } };

字典首先找到a這個變數,得到了存儲著數據的地址A。

隨後將地址A中的內容複製,並粘貼到字典開闢出的另一塊記憶體空間中。而這個記憶體空間的地址是地址B。

此時,無論我們給變數a如何賦值,字典中的a是不會改變的。

因為在給變數a賦值時,實際修改的是地址為A的記憶體空間中的數據,而字典中的a存儲在的位置是地址為B的記憶體空間中。

 

可是,如果按照這個結論來看,在本文開頭部分我用的第二種方法,也應該是在外部修改了類中成員的數據後,字典中的內容不變啊?

那為什麼在外部修改的時候字典內的內容也改變了呢?

 

當我們寫下以下代碼的時候:

 1 namespace Example
 2 {
 3     public partial class MainWindow : Window
 4     {
 5         private void Window_Loaded(object sender, RoutedEventArgs e)
 6         {
 7             public static MyClass staff = new MyClass(); 
 8         }
 9     }
10 
11     Class MyClass 
12     {
13         public int a;
14         public int b;
15         public int c;
16     }
17 }

變數staff中,存儲了一個地址A,地址A處存儲了MyClass這樣的一個類型,也就是a、b和c三個變數。

而a、b和c三個變數,實際上是分別存儲了地址a,地址b,地址c。

這三個地址所指向的地方,才是各自存儲了數據的記憶體空間。

 

當我們將staff添加到字典中時,字典讀取到了地址A,並將地址A處存儲的內容複製到了自己新開闢的、在地址B處的記憶體空間中。

在複製的時候,a、b、c三個變數的地址也就隨著被覆制到了地址B處中。

 

這個時候,外部的變數staff和字典中的staff,都會指向同樣的三塊記憶體空間。

當通過外部變數staff修改內容時,由於字典內的staff實際也訪問的是同樣的地址,所以字典內的內容也會隨之改變。

 

這樣說起來可能有點亂,用圖來表示應該會明瞭一些。

 

以上均為本人理解,如有疏漏還請各位多多指教。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、Celery 核心模塊 1. Brokers brokers 中文意思為中間人,在這裡就是指任務隊列本身,接收生產者發來的消息即Task,將任務存入隊列。任務的消費者是Worker,Brokers 就是生產者和消費者存放/拿取產品的地方(隊列)。Celery 扮演生產者和消費者的角色。 常見的 ...
  • 1.包裝類是什麼? java中我們經常將基本數據類型轉換為對象,例:將基本數據類型存儲到object[]數組或集合中進行操作 為瞭解決這個問題,Java在設計類的時候為每個基本數據類型設計了一個對應的類進行代表 這八個和基本數據類型對應的類統稱包裝類 包裝類位於java.lang包下 以下是八種數據 ...
  • 一、下載tomcat源碼 https://github.com/apache/tomcat/tree/8.5.x 二、建立pom 1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/PO ...
  • 使用TimerTask創建定時任務,打包之後應用於linux系統 step1:創建java項目 step2:代碼實現 定時任務實現類CreateTask.java是列印操作者的名字 配置準換類Configuration.java 調用ParseConfig的方法convertExecutor()讀取 ...
  • HTTP–Response詳解 博客說明 文章所涉及的資料來自互聯網整理和個人總結,意在於個人學習和經驗彙總,如有什麼地方侵權,請聯繫本人刪除,謝謝! 響應消息數據格式 響應行 組成:協議/版本 響應狀態碼 狀態碼描述 響應狀態碼:伺服器告訴客戶端瀏覽器本次請求和響應的一個狀態 態碼都是3位數字 分 ...
  • 由於在ubuntu環境下,將python做與python3.6做了軟鏈接(ln -s python python3.6),並且pip也被我做了軟鏈接,所以導致用pip安裝virtualenvwrapper之後,在source啟動virtualenvwrapper.sh時以及workon 虛擬環境時總 ...
  • 發文前,說下寫這個的緣故。本來以為自己對java內部類瞭解,其實是我太過於不覺得、以為不重要!所以,今天在重新寫下Demo,為自己記錄一下、回顧一下。 開始~~~ 重新理解什麼是內部類以及寫法、定義等; 代碼一: 1 package com.yk.nbn; 2 /** 3 * @author yk ...
  • 完整逆波蘭計算器(Java) 博客說明 文章所涉及的資料來自互聯網整理和個人總結,意在於個人學習和經驗彙總,如有什麼地方侵權,請聯繫本人刪除,謝謝! 功能 支持 + - * / ( ) 多位數,支持小數, 相容處理, 過濾任何空白字元,包括空格、製表符、換頁符 基本思路 中綴表達式轉尾碼表達式 代碼 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...