C#淺拷貝與深拷貝區別

?

也許會有人這樣解釋C# 中淺拷貝與深拷貝區別:

??????? 淺拷貝是對引用類型拷貝地址,對值類型直接進行拷貝。

不能說它完全錯誤,但至少還不夠嚴謹。比如:string 類型咋說?

?

其實,我們可以通過實踐來尋找答案。

首先,定義以下類型:

int 、string 、enum 、struct 、class 、int[ ] 、string[ ]

代碼如下:

????//枚舉
????public?enum?myEnum
????{?_1?=?1,?_2?=?2?}
?
????//結構體
????public?struct?myStruct
????{
????????public?int?_int;
????????public?myStruct(int?i)
????????{?_int?=?i;?}
????}
?
????//
????class?myClass
????{
????????public?string?_string;
????????public?myClass(string?s)
????????{?_string?=?s;?}
????}
?
????//ICloneable:創建作為當前實例副本的新對象。
????class?DemoClass?:?ICloneable
????{
????????public?int?_int?=?1;
????????public?string?_string?=?"1";
????????public?myEnum?_enum?=?myEnum._1;
????????public?myStruct?_struct?=?new?myStruct(1);
????????public?myClass?_class?=?new?myClass("1");
????????//數組
????????public?int[]?arrInt?=?new?int[]?{?1?};
????????public?string[]?arrString?=?new?string[]?{?"1"?};
?
????????//返回此實例副本的新對象
????????public?object?Clone()
????????{
????????????//MemberwiseClone:返回當前對象的淺表副本(它是Object對象的基方法)
????????????return?this.MemberwiseClone();
????????}
????}

注意:

ICloneable 接口:支持克隆,即用與現有實例相同的值創建類的新實例。

MemberwiseClone 方法:創建當前 System.Object 的淺表副本。

?

接下來,構建實例A ,并對實例A 克隆產生一個實例B
然后,改變實例B 的值,并觀察實例A 的值會不會被改變。

代碼如下:

class?淺拷貝與深拷貝
{
????static?void?Main(string[]?args)
????{
????????DemoClass?A?=?new?DemoClass();
????????//創建實例A的副本?-->?新對象實例B
????????DemoClass?B?=?(DemoClass)A.Clone();
?
????????B._int?=?2;
????????Console.WriteLine("?int?\t\t??A:{0}??B:{1}",?A._int,?B._int);
?
????????B._string?=?"2";
????????Console.WriteLine("?string?\t??A:{0}??B:{1}",?A._string,?B._string);
?
????????B._enum?=?myEnum._2;
????????Console.WriteLine("?enum?\t\t??A:{0}??B:{1}",?(int)A._enum,?(int)B._enum);
?
????????B._struct._int?=?2;
????????Console.WriteLine("?struct?\t??A:{0}??B:{1}",?
????????????????????????? A._struct._int,?B._struct._int);
?
????????B._class._string?=?"2";
????????Console.WriteLine("?class?\t\t??A:{0}??B:{1}",?
????????????????????????? A._class._string,?B._class._string);
?
????????B.arrInt[0]?=?2;
????????Console.WriteLine("?intArray?\t??A:{0}??B:{1}",?
????????????????????????? A.arrInt[0],?B.arrInt[0]);
?
????????B.arrString[0]?=?"2";
????????Console.WriteLine("?stringArray?\t??A:{0}??B:{1}",?
????????????????????????? A.arrString[0],?B.arrString[0]);
?
????????Console.ReadKey();
????}
}

結果如下:

2010-09-08_221736

從最后的輸出結果,我們得知:

對于內部的Class 對象和數組,則Copy 一份地址。[ 改變B 時,A也被改變了 ]

而對于其它內置的int / string / enum / struct / object 類型,則Copy 一份值。

?

有一位網友說:string 類型雖然是引用類型,但是很多情況下.Net 把string 做值類型來處理,我覺得string 應該也是按照值類型處理的。

這說明他對string 類型還不夠了解。

可以肯定的是:string 一定是引用類型。那它為什么是深拷貝呢?

如果你看一下string 類型的源代碼就知道了:

//表示空字符串。此字段為只讀。
public?static?readonly?string?Empty;

答案就在于 string 是 readonly 的,當改變 string 類型的數據值時,將重新分配了內存地址。

?

下面引用一段網友的代碼:Vseen[ Aloner ] 的個人陋見:

public?class?Student
{
?? //?這里用“字段”,其實應當是屬性。
?? public?string?Name;
?? public?int?Age;
?? //自定義類?Classroom
?? public?Classroom?Class;
}
淺拷貝:Student?A?淺拷貝出?Student?B,Name和Age擁有新的內存地址,但引用了同一個?Classroom。
深拷貝:Student?A?淺拷貝出?Student?B,Name和Age擁有新的內存地址,并且A.Classroom?的內存地址不等于?B.Classroom。
?
其實俗點講,有點像:
?
public?object?Clone()
{
?? Student?B?=?new?Student();
?? B.Name?=?this.Name;
?? B.Age?=?this.Age;
?? //淺拷貝
?? B.Class?=?this.Class;
?? //深拷貝
?? B.Class?=?new?Classromm();
?? B.Class.Name?=?this.Class.Name;
?? B.Class.Teacher?=?this.Class.Teacher;
?? //根據情況,對Teacher 進行判定要進行的是深拷貝,還是淺拷貝。
}

?

淺拷貝:給對象拷貝一份新的對象。

淺拷貝的定義 —— 只對值類型(或string)類型分配新的內存地址。


深拷貝:給對象拷貝一份全新的對象。

深拷貝的定義 —— 對值類型分配新的內存地址,引用類型、以及引用類型的內部字段分配的新的地址。

我是這么定義的:淺拷貝,換湯不換藥。

?

注意:

1、在 .NET 程序中,應該避免使用 ICloneable 接口。

????? 因為通過該接口無法判斷究竟是淺拷貝還是深拷貝,這會造成誤解或誤用。

?

2、深拷貝應該復制該對象本身及通過該對象所能到達的完整的對象圖,淺拷貝只復制對象本身(就是該對象所表示的在堆中的一塊連續地址中的內容)。

?

個人愚見:

Clone :深層拷貝,拷貝到了指針指向的內存塊的值。

?

淺拷貝:僅僅拷貝了指針的內容。(只是給一個對象多起了個名字,所以,當改變拷貝的某個屬性的時候,原對象的對應屬性亦會改變)。

?

?

?

淺拷貝:是指將對象中的所有字段逐字復雜到一個新對象。

對值類型字段只是簡單的拷貝一個副本到目標對象,改變目標對象中值類型字段的值不會反映到原始對象中,因為拷貝的是副本;
對引用型字段則是指拷貝他的一個引用到目標對象。改變目標對象中引用類型字段的值它將反映到原始對象中,因為拷貝的是指向堆是上的一個地址;

深拷貝:深拷貝與淺拷貝不同的是對于引用字段的處理,深拷貝將會在新對象中創建一個新的對象和原始對象中對應字段相同(內容相同)的字段,也就是說這個引用和原始對象的引用是不同, 我們改變新對象中這個字段的時候是不會影響到原始對象中對應字段的內容。

推薦:
C#中的深復制和淺復制(在C#中克隆對象)
由淺拷貝討論到深拷貝再討論到接口(一):淺拷貝和深拷貝?
6個重要的.NET概念:棧,堆,值類型,引用類型,裝箱,拆箱
C# 讀書筆記 ---- 淺度復制與深度復制

?

?

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

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

相關文章

內網安裝nginx+keepalived環境配置及簡單使用

分享一下這次艱難的配置過程,銜接上一篇的配置內網獨立IP虛擬機。 先吐槽一波,由于公司網絡屬于內網,與外網互不相通,所以在安裝nginx的時候可能會去外網找相對應rpm文件,而且也有許多的版本不兼容問題,好…

cad連續標注數字123怎么弄_實例講解CAD模型與布局中的各種比例

好課推薦:零基礎CAD:點我CAD室內:點我 周站長CAD:點我CAD機械:點我 Bim教程:點我CAD建筑:點我CAD三維:點我全屋定制:點我 ps教程:點我蘋果版CAD:點我 3dmax教…

SpringMvc異步請求的使用及部分原理

最近隔壁項目組的項目又出問題了,一直被用戶投訴太卡了,頁面白屏的那種,打開源代碼一看,全是非異步請求,類似于以下寫法: ResponseBodyRequestMapping(value "/getTest")public String getTest(…

Microsoft BizTalk ESB Toolkit 2.0

[>>> 更多<BizTalk開發系列>文章 ] 微軟于6月8號發布了BizTalk Server 2009企業集成平臺的最后一個功能組件:ESB Toolkit 2.0 (原名:ESB Guidance 2.0)&#xff0c;ESB ToolKit 2.0一個是工具和代碼集擴展了BizTalk Server 2009對于松耦合和動態消息架構的支持…

python解釋器環境中用于表示上一次運算結果的特殊變量_判斷正誤 PUSH CL_學小易找答案...

【單選題】將數學關系式2 【填空題】請用4位十六進制寫出每條指令結束后AX的值。 MOV AX, 0 DEC AX ADD AX, 7FFFH ADC AX, 1 NEG AX OR AX, 3FDFH AND AX, 0EBEDH XCHG AH, AL SAL AX, 1 RCL AX, 1 【判斷題】判斷正誤 MOV DX, 09H 【判斷題】判斷正誤 MOV [1200H], [SI] 【單…

Java線程的使用及共享協作

創建線程的三種方式 1、繼承Thread&#xff1b; static class MyThread extends Thread{Overridepublic void run() {//do something...} } public static void main(String[] args) throws InterruptedException {MyThread thread new MyThread ();thread.start(); } 2、實…

WCF學習筆記(三):開啟net.tcp端口

正在做一個使用tcp協議的WCF示例&#xff0c;遇到很多問題。首當其沖的問題就是——如何為WCF打開tcp端口。。。 具體步驟如下&#xff1a; 1、在IIS中為WCF安裝支持TCP協議的組件&#xff1a; 2、在防火墻的入棧規則中開啟808端口&#xff1b; 3、在servies.msc中打開兩個服務…

孿生神經網絡_軒轅實驗室:數字孿生:基于機器學習的汽車數字孿生模型

本文來源&#xff1a;A. Rassolkin, T. Vaimann, A. Kallaste, and V. Kuts, “Digital twin for propulsion drive of autonomous electric vehicle,” in 2019 IEEE 60th International Scientific Conference on Power and Electrical Engineering of Riga Technical Univer…

Java線程Fork/Join思想及實現

最近在看線程這一塊的東西&#xff0c;所以之前的那篇文章就是用來記錄的&#xff0c;但看起來好簡單的樣子&#xff0c;哈哈哈&#xff01; 這兩天看的是Fork/Join 分而治之的思想&#xff0c;Doug Lea大師的JUC還是挺強的&#xff0c;學并發編程應該沒有人不知道這個大佬吧&…

Sgen.exe: Speed up XmlSerializer's Startup Performance [.NET 2.0, XML Serialization]

Sgen.exe: Speed up XmlSerializers Startup Performance [.NET 2.0, XML Serialization] Written by Allen Lee 1. Why Sgen.exe? 在《Serialize Your Deck with Positron [XML Serialization, XSD, C#]》一文中&#xff0c;我們領略到 XML Serialization 是如何簡化我們的 X…

Java線程并發常用工具類使用

這次整理了一些比較常用的線程工具類啦。 CountDownLatch&#xff1a;在一組線程執行完后&#xff0c;才能開始執行調用等待的線程。上片文章提到過junit的測試盡量不要測試線程&#xff0c;如果硬是要可以使用CountDownLatch進行測試 CyclicBarrier&#xff1a;在一組線程中…

三維圖形幾何變換算法實驗_計算機視覺方向簡介 | 深度學習視覺三維重建

點擊上方“計算機視覺life”&#xff0c;選擇“星標”快速獲得最新干貨作者&#xff1a; Moonsmilehttps://zhuanlan.zhihu.com/p/79628068本文已由作者授權&#xff0c;未經允許&#xff0c;不得二次轉載三維重建意義三維重建作為環境感知的關鍵技術之一&#xff0c;可用于自動…

讀《高效程序員的45個習慣——敏捷開發修煉之道》

本書主要用平易的語言講述了45個有助于提高程序員自身敏捷的習慣&#xff0c;個人感覺這種老外寫的書翻譯成中文就少了很多意思。 主要的45個習慣是&#xff1a; 做事欲速則不達對事不對人排除萬難跟蹤變化對團隊投資懂得丟棄打破沙鍋問到底把握開發節奏讓客戶做決定讓設計指導…

Java線程CAS原子操作

這次分享一些關于原子操作(CAS)的東西. 定義 CAS(Compare And Swap)是CPU的一個指令級別的操作&#xff0c;叫原子操作&#xff0c;原子操作是不可分割的&#xff0c;跟事務差不多&#xff0c;要么全部執行完成&#xff0c;要么不執行&#xff1b; 像這種操作有點類似阻塞鎖…

python 導航欄_解析導航欄的url--selnium,beautifulsoup實戰

前段時間做ui自動化測試的時候&#xff0c;導航欄菜單始終有點問題&#xff0c;最后只好直接獲取到url&#xff0c;然后直接使用driver.get(url)進入頁面&#xff1b;包括做壓測的時候&#xff0c;比如我要找出所有報表菜單的url&#xff0c;這樣不可能手動去一個一個找出來&am…

PNG圖片詳解

1、PNG圖片類型 PNG格式有8位、24位、32位三種&#xff0c;下面是一些術語&#xff1a; 索引透明&#xff1a;類似于GIF&#xff0c;某一像素只有全透和全不透明兩種效果Alpha透明&#xff1a;半透明PNG8 8位的PNG最多支持256&#xff08;2的8次方&#xff09;種顏色&#xff0…

Java并發編程之顯式鎖(Lock)使用

又是一個基于AQS好用的類&#xff0c;看來下次有必要看看AQS了&#xff0c;正好又是放假。 既然叫顯式鎖&#xff0c;必然也有隱式鎖&#xff0c;也就是所謂的synchronzied關鍵字&#xff0c;它們兩者的區別呢在于使用范圍&#xff0c;synchronzied關鍵字的使用范圍比Lock要小…

python pychart三維_詳解python模塊pychartdir安裝及導入問題

在遷移別人寫好的腳本時&#xff0c;發現pychartdir沒有導入&#xff0c;腳本執行報錯。以下是報錯內容&#xff1a;[modpsLGJF-ZYC5-MMSC-WEB02 ~]$ python /opt/aspire/product/modps/mopps/shell/dayreport_linux.py/etc/host.conf: line 1: bad command nospoof on"Tr…

vim 中Ctags的安裝和使用

Ctags是一個用來為源文件中的標識符&#xff08;如變量、函數、類成員、宏定義等&#xff09;創建索引文件的程序。這些tags文件能被編輯器或其它工具用來快速查找定位源代碼中的符號&#xff08;tag/symbol&#xff09;&#xff0c;如變量名&#xff0c;函數名等。 Tags文件中…

Java并發編程之AbstractQueuedSynchronizer(AQS)源碼解析

自己一個人隨便看看源碼學習的心得&#xff0c;分享一下啦&#xff0c;不過我覺得還是建議去買本Java并發編程的書來看會比較好點&#xff0c;畢竟個人的理解有限嘛。 獨占鎖和共享鎖 首先先引入這兩個鎖的概念&#xff1a;獨占鎖即同一時刻只有一個線程才能獲取到鎖&#xf…