自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

淺談C#結(jié)構(gòu)

開(kāi)發(fā) 后端
結(jié)構(gòu)是一種值類型,并且不需要堆分配。結(jié)構(gòu)的實(shí)例化可以不使用new運(yùn)算符。如果聲明一個(gè)10000個(gè)Point對(duì)象組成的數(shù)組,為了引用每個(gè)對(duì)象,則需分配更多內(nèi)存;這種情況下,使用結(jié)構(gòu)可以節(jié)約資源。

  結(jié)構(gòu)是使用 struct關(guān)鍵字定義的,與類相似,都表示可以包含數(shù)據(jù)成員和函數(shù)成員的數(shù)據(jù)結(jié)構(gòu)。

  一般情況下,我們很少使用結(jié)構(gòu),而且很多人也并不建議使用結(jié)構(gòu),但作為.NET Framework 一般型別系統(tǒng)中的一個(gè)基本架構(gòu),還是有必要了解一下的。

  結(jié)構(gòu)的特征:

  結(jié)構(gòu)是一種值類型,并且不需要堆分配。結(jié)構(gòu)的實(shí)例化可以不使用new運(yùn)算符。

  在結(jié)構(gòu)聲明中,除非字段被聲明為 const 或 static,否則無(wú)法初始化。結(jié)構(gòu)類型永遠(yuǎn)不是抽象的,并且始終是隱式密封的,因此在結(jié)構(gòu)聲明中不允許使用abstract和sealed修飾符。

  結(jié)構(gòu)不能聲明默認(rèn)構(gòu)造函數(shù)(沒(méi)有參數(shù)的構(gòu)造函數(shù))或析構(gòu)函數(shù),但可以聲明帶參數(shù)的構(gòu)造函數(shù)。結(jié)構(gòu)可以實(shí)現(xiàn)接口,但不能從另一個(gè)結(jié)構(gòu)或類繼承,而且不能作為一個(gè)類的基,所有結(jié)構(gòu)都直接繼承自 System.ValueType,后者繼承自 System.Object。結(jié)構(gòu)在賦值時(shí)進(jìn)行復(fù)制。將結(jié)構(gòu)賦值給新變量時(shí),將復(fù)制所有數(shù)據(jù),并且對(duì)新副本所做的任何修改不會(huì)更改原始副本的數(shù)據(jù)。在使用值類型的集合(如 Dictionary<string, myStruct>)時(shí),請(qǐng)務(wù)必記住這一點(diǎn)。結(jié)構(gòu)類型的變量直接包含了該結(jié)構(gòu)的數(shù)據(jù),而類類型的變量所包含的只是對(duì)相應(yīng)數(shù)據(jù)的一個(gè)引用(被引用的數(shù)據(jù)稱為“對(duì)象”)。但是結(jié)構(gòu)仍可以通過(guò)refout參數(shù)引用方式傳遞給函數(shù)成員。結(jié)構(gòu)可用作可以為 null 的類型,因而可向其賦 null 值。structA

  1.   {publicintx; //不能直接對(duì)其進(jìn)行賦值publicinty;  
  2.   public static stringstr = null//靜態(tài)變量可以初始化publicA(intx,inty) //帶參數(shù)的構(gòu)造函數(shù)  
  3.   {this.x =x;this.y =y;  
  4.   Console.WriteLine("x={0},y={1},str={2}", x, y,str);  
  5.   }  
  6.   }classProgram  
  7.   {staticvoidMain(string[] args)  
  8.   {  
  9.   A a =newA(1,2);  
  10.   A a1 =a;  
  11.   a.x =10;  
  12.   Console.WriteLine("a1.x={0}",a1.x);  
  13.   Console.Read();  
  14.   }  
  15.   } 

  結(jié)果為:x=1,y=2,str=

  a1.x=1

  此時(shí)a1.x值為1是因?yàn)椋瑢賦值給a1是對(duì)值進(jìn)行復(fù)制,因此,a1不會(huì)受到a.x賦值得改變而改變。

  但如果A是類,這時(shí)a和a1里的x引用的是同一個(gè)地址,則a1.x的值會(huì)輸出10。

  結(jié)構(gòu)的裝箱與拆箱我們知道,一個(gè)類類型的值可以轉(zhuǎn)換為object類型或由該類實(shí)現(xiàn)的接口類型,這只需在編譯時(shí)把對(duì)應(yīng)的引用當(dāng)作另一個(gè)類型處理即可。

  與此類似,一個(gè)object類型的值或者接口類型的值也可以被轉(zhuǎn)換回類類型而不必更改相應(yīng)的引用。當(dāng)然,在這種情況下,需要進(jìn)行運(yùn)行時(shí)類型檢查。由于結(jié)構(gòu)不是引用類型,上述操作對(duì)結(jié)構(gòu)類型是以不同的方式實(shí)現(xiàn)的。

  當(dāng)結(jié)構(gòu)類型的值被轉(zhuǎn)換為object類型或由該結(jié)構(gòu)實(shí)現(xiàn)的接口類型時(shí),就會(huì)執(zhí)行一次裝箱操作。

  反之,當(dāng) object類型的值或接口類型的值被轉(zhuǎn)換回結(jié)構(gòu)類型時(shí),會(huì)執(zhí)行一次拆箱操作。

  與對(duì)類類型進(jìn)行的相同操作相比,主要區(qū)別在于:

  裝箱操作會(huì)把相關(guān)的結(jié)構(gòu)值復(fù)制為已被裝箱的實(shí)例,而拆箱則會(huì)從已被裝箱的實(shí)例中復(fù)制出一個(gè)結(jié)構(gòu)值。

  因此,在裝箱或拆箱操作后,對(duì)“箱”外的結(jié)構(gòu)進(jìn)行的更改不會(huì)影響已被裝箱的結(jié)構(gòu)。structProgram

  1.   {staticvoidMain(string[] args)  
  2.   {inti =1;objecto =i; //隱式裝箱  
  3.   i =123;  
  4.   Console.WriteLine("i={0},o={1}",i,o);  
  5.   Console.Read();  
  6.   }  
  7.   }  
  8.   //結(jié)果為:i=123,o=1 

  結(jié)構(gòu)與構(gòu)造函數(shù)我們知道結(jié)構(gòu)不能使用默認(rèn)的構(gòu)造函數(shù),只能使用帶參數(shù)的構(gòu)造函數(shù),當(dāng)定義帶參數(shù)的構(gòu)造函數(shù)時(shí),一定要完成結(jié)構(gòu)所有字段的初始化,如果沒(méi)有完成所有字段的初始化,編譯時(shí)會(huì)發(fā)生錯(cuò)誤。結(jié)構(gòu)可以使用靜態(tài)構(gòu)造函數(shù)嗎?

  可以,結(jié)構(gòu)的靜態(tài)構(gòu)造函數(shù)與類的靜態(tài)構(gòu)造函數(shù)所遵循的規(guī)則大體相同。

  結(jié)構(gòu)的靜態(tài)構(gòu)造函數(shù)何時(shí)將觸發(fā)呢?結(jié)構(gòu)的實(shí)例成員被引用,結(jié)構(gòu)的靜態(tài)成員被引用,結(jié)構(gòu)顯示聲明的構(gòu)造函數(shù)被調(diào)用。但是創(chuàng)建結(jié)構(gòu)類型的默認(rèn)值不會(huì)觸發(fā)靜態(tài)構(gòu)造函數(shù)。

  為什么結(jié)構(gòu)不能自定義無(wú)參數(shù)的構(gòu)造函數(shù)?

  結(jié)構(gòu)類型的構(gòu)造函數(shù)與類的構(gòu)造函數(shù)類似,用來(lái)初始化結(jié)構(gòu)的成員變量,但是struct不能包含顯式默認(rèn)構(gòu)造函數(shù),

  因?yàn)榫幾g器將自動(dòng)提供一個(gè)構(gòu)造函數(shù),此構(gòu)造函數(shù)將結(jié)構(gòu)中的每個(gè)字段初始化為默認(rèn)值表中顯示的默認(rèn)值。

  然而,只有當(dāng)結(jié)構(gòu)用new實(shí)例化時(shí),才會(huì)調(diào)用此默認(rèn)構(gòu)造函數(shù)。對(duì)值類型調(diào)用默認(rèn)構(gòu)造函數(shù)不是必需的。

  1.   structA  
  2.   {staticA()  
  3.   {  
  4.   Console.WriteLine("I am A.");  
  5.   }publicvoidFun()  
  6.   {  
  7.   }  
  8.   }classProgram  
  9.   {staticvoidMain(string[] args)  
  10.   {  
  11.   A a=newA();  
  12.   a.Fun(); //結(jié)構(gòu)的實(shí)例成員被引用  
  13.   Console.Read();  
  14.   }  
  15.   } 

結(jié)果為:I am A.

  結(jié)構(gòu)與繼承:

  一個(gè)結(jié)構(gòu)聲明可以指定實(shí)現(xiàn)的接口列表,但是不能指定基類。

  由于結(jié)構(gòu)不支持類與結(jié)構(gòu)的繼承,所以結(jié)構(gòu)成員的聲明可訪問(wèn)性不能是protected或protectedinternal。結(jié)構(gòu)中的函數(shù)成員不能是abstract或 virtual,因而override修飾符只適用于重寫(xiě)從System.ValueType繼承的方法。

  為在設(shè)計(jì)編程語(yǔ)言時(shí)將結(jié)構(gòu)設(shè)計(jì)成無(wú)繼承性?

  其實(shí)類的繼承是有相當(dāng)?shù)某杀镜?——由于繼承性,每個(gè)類需要用額外的數(shù)據(jù)空間來(lái)存儲(chǔ)“繼承圖”來(lái)表示類的傳承歷史,

  通俗地說(shuō)來(lái)就是我們?nèi)祟惖募易寮易V,里面存儲(chǔ)著我們的祖宗十八代,只有這樣我們才知道我們從哪里來(lái)的,而家譜肯定是需要額外的空間來(lái)存放的。

  大家不要覺(jué)得這個(gè)存放“繼承圖”的空間很小,如果我們的程序需要用10000個(gè)點(diǎn)(Point)來(lái)存放游戲中的人物形體數(shù)據(jù)的話,

  在一個(gè)場(chǎng)景中又有N個(gè)人,這個(gè)內(nèi)存開(kāi)銷可不是小數(shù)目了。所以我們可以通過(guò)將點(diǎn)(Point)申明成 Struct而不是class來(lái)節(jié)約內(nèi)存空間。interfaceITest

  1.   {voidFun(intx,inty);  
  2.   }structA:ITest  
  3.   {publicvoidFun(intx,inty) //隱式實(shí)現(xiàn)接口里的方法  
  4.   {  
  5.   Console.WriteLine("x={0},y={1}", x, y);  
  6.   }  
  7.   }classProgram  
  8.   {staticvoidMain(string[] args)  
  9.   {  
  10.   A a; //結(jié)構(gòu)的實(shí)例化可以不使用new  
  11.   a.Fun(1, 2);  
  12.   Console.Read();  
  13.   }  
  14.   }  
  15.   // 結(jié)果為:x=1,y=2 

  什么情況下結(jié)構(gòu)的實(shí)例化可以不使用new?

  當(dāng)結(jié)構(gòu)中沒(méi)有參數(shù)時(shí),結(jié)構(gòu)的實(shí)例化可以不使用new;當(dāng)結(jié)構(gòu)中有參數(shù)時(shí),必須對(duì)結(jié)構(gòu)中所有參數(shù)進(jìn)行初始化后,才能不使用new對(duì)結(jié)構(gòu)進(jìn)行實(shí)例化。什么時(shí)候使用結(jié)構(gòu)?

  結(jié)構(gòu)體適合一些小型數(shù)據(jù)結(jié)構(gòu),這些數(shù)據(jù)結(jié)構(gòu)包含的數(shù)據(jù)以創(chuàng)建結(jié)構(gòu)后不修改的數(shù)據(jù)為主;

  例如:struct類型適于表示Point、Rectangle和Color等輕量對(duì)象。

  盡管可以將一個(gè)點(diǎn)表示為類,但在某些情況下,使用結(jié)構(gòu)更有效。

  如果聲明一個(gè)10000個(gè)Point對(duì)象組成的數(shù)組,為了引用每個(gè)對(duì)象,則需分配更多內(nèi)存;這種情況下,使用結(jié)構(gòu)可以節(jié)約資源。

  定義的時(shí)候不會(huì)用到面向?qū)ο蟮囊恍┨匦裕?/p>

  結(jié)構(gòu)體在不發(fā)生裝箱拆箱的情況下性能比類類型是高很多的.

原文鏈接:http://www.cnblogs.com/jiajiayuan/archive/2011/09/20/2181582.html

【編輯推薦】

  1. 詳解C#中不同類的類型
  2. 淺談C#中標(biāo)準(zhǔn)Dispose模式的實(shí)現(xiàn)
  3. C#選擇正確的集合進(jìn)行編碼
  4. C# 4.0新特性:協(xié)變與逆變中的編程思想
  5. C#應(yīng)用Attribute特性 代碼統(tǒng)計(jì)分析
責(zé)任編輯:彭凡 來(lái)源: 博客園
相關(guān)推薦

2009-08-07 11:26:53

C#數(shù)組結(jié)構(gòu)

2009-08-13 15:03:58

C#結(jié)構(gòu)體變量

2009-08-20 18:30:33

C# ReaderWr

2009-08-12 11:24:25

C# String對(duì)象

2009-08-19 17:12:18

C# Connecti

2009-08-31 09:37:09

C# Employee

2009-08-25 16:16:43

C# oledbcon

2009-08-26 15:46:01

C#匿名類型

2009-08-06 15:30:23

C#類型系統(tǒng)

2009-08-14 17:58:05

C#接口方法

2009-08-26 13:15:38

C#選擇控制

2009-09-02 15:41:21

C# HTTPWebR

2009-08-20 10:24:52

C#開(kāi)發(fā)WinForm

2009-08-10 10:04:25

C#抽象類C#接口

2009-08-27 14:44:11

C# interfac

2009-08-10 14:55:04

C#定義Nullabl

2009-08-18 17:08:50

C#編寫(xiě)XML文檔

2009-08-25 13:26:49

C#編寫(xiě)asp+

2009-09-04 11:00:13

通過(guò)C#引用傳遞

2009-08-19 17:45:26

C#使用GDI+
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)