久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

C#中的結構體與類的區(qū)別

 行動如風的蝸牛 2018-06-20

經(jīng)常聽到有朋友在討論C#中的結構與類有什么區(qū)別.正好這幾日閑來無事,自己總結一下,希望大家指點.

1. 首先是語法定義上的區(qū)別啦,這個就不用多說了.定義類使用關鍵字class 定義結構使用關鍵字struct.在語法上其實類和結構有著很多相似的地方.

   定義類的語法    

復制代碼
 1 class Person
 2 {
 3    private string name;
 4    private int age;
 5    
 6    public void SayHi()
 7    {
 8        Console.WriteLine("Hello,My Name is "+this.name+",My Age is "+this.age);
 9    }
10 }
復制代碼

    定義結構的語法. 

復制代碼
 1     struct Rectangle
 2     {
 3         private int width;
 4         private int height;
 5          
 6         public int GetArea()
 7         {
 8             return this.width * height;
 9         }
10     }
復制代碼

    從語法上來看.它們的語法都大同小異,類里面的成員幾乎都可以定義在結構體中,但是析構函數(shù)除外.這是為什么呢?后面解答.

2. 雖然我們說它們的語法極其相似,但是它們在語法還是有幾點區(qū)別的.

   a.在結構體中可以聲明字段,但是聲明字段的時候是不能給初始值的.所以當我們試圖這樣寫代碼的時候,C#編譯器在將源代碼編譯成程序集的是會提示語法錯誤.

       

   我們知道如果我們在類中聲明1個字段的同時給這個字段賦初始值,這樣是可以滴,就像下面這樣. 

class Person
{
   private string name ="jack";
}

    但是如果像下面這樣確實不行滴.聲明完1個字段,再為這個字段賦值,就像下面這樣. 

1 class Person
2 {
3    private string name;
4    name="jack";
5 }

 

    所以我們說,在類下面只能直接定義類的成員,只能定義.  比如定義成員字段,屬性 方法 構造函數(shù)等等.上面那樣的代碼name="jack"這樣的代碼我們稱之為“執(zhí)行代碼”,意思就是說這些代碼只有在被執(zhí)行的時候才會有效果.而你試想一下,那么這些代碼什么時候被執(zhí)行呢? 創(chuàng)建類的對象的時候? 那還用得著構造函數(shù)嗎? 經(jīng)??吹揭恍┏鯇W者在類的下面直接寫這樣代碼.

 

    但是又有人會說了.誒, 那么為什么在聲明類的字段的時候可以賦值呢?賦值表達式也是1個執(zhí)行代碼啊?為什么這樣就不報錯呢?給你看看下面的代碼 你就會知道其中的真相了.

     

     當我們使用C#編譯器將這段代碼編譯為程序集的時候,看看微軟為我們生成的代碼吧.

     

     展開構造函數(shù),看看這里面有什么蹊蹺吧,!

     

     是的,C#編譯器在編譯的時候,如果我們聲明字段的時候為字段賦值,那么為字段賦值的代碼C#編譯器在編譯的時候會將賦值的代碼放到構造函數(shù)中去,其實嚴格意義上來說,類的字段也是不能有初始值的.只不過微軟在背后幫我們做了點事情,我們不知道而已.

     所以,不管在類和結構中,執(zhí)行代碼一定要寫在方法中.不能直接寫在結構或者類的下面.因為當執(zhí)行代碼寫在方法中了,那么這些執(zhí)行代碼的執(zhí)行時機才可以確定,就是這個方法被調(diào)用的時候了.

    從上面的內(nèi)容,我們可以看出.其實從本質(zhì)上來說,類和結構的字段都是不能有初始值的.只不過微軟在語法上允許我們在定義類的字段的時候為其賦值.但是背后微軟其實是把賦值的執(zhí)行代碼放到構造函數(shù)中去執(zhí)行的. 而結構體微軟卻不幫我們這樣做.至于這其中是什么原因.查了些資料,也看了園子里其他博友的文章,感覺都不能說服我,但是自己也想不出1個確切的理由微軟為什么要這樣做.那就先放著吧,希望參透其中原理的童鞋能指點.

 

    b. 關于構造函數(shù).

    首先,關于隱式構造函數(shù).我們知道,在1個類中如果我們沒有為類寫任意的構造函數(shù),那么C#編譯器在編譯的時候會自動的為這個類生成1個無參數(shù)的構造函數(shù).我們將這個構造函數(shù)稱之為隱式構造函數(shù) 但是一旦我們?yōu)檫@個類寫了任意的1個構造函數(shù)的時候,這個隱式的構造函數(shù)就不會自動生成了.

    在結構中,就不是這樣了,在結構中隱式的構造函數(shù)無論如何都存在.看看代碼吧.

    在下面的代碼中 我們?yōu)榻Y構體寫了1個帶參數(shù)的構造函數(shù).如下.

    

    我們使用new關鍵字來創(chuàng)建結構體對象,我們發(fā)現(xiàn)調(diào)用構造函數(shù)的時候,提示是有兩個構造函數(shù)的.多了1個無參數(shù)的構造函數(shù).

     

   那么 我們再想,能不能手動的寫1個無參數(shù)的構造函數(shù)呢?我們懷著無比激動的心情,試一下.

   

  結果是華麗麗的報錯了.所以我們得出結論. 隱式的無參數(shù)的構造函數(shù)在結構中無論如何都是存在的,所以程序員不能手動的為結構添加1個無參數(shù)的構造函數(shù).

  關于構造函數(shù)當然還不僅僅如此.我們知道在類的構造函數(shù)中我們可以寫一些任意的代碼(前提是符合C#語法啦),在結構體的構造函數(shù)中雖然也可以寫任意的代碼.但是C#語法規(guī)定在結構體的構造函數(shù)中,必須要為結構體的所有字段賦值.看看下面的代碼吧.

   

   啊哦.....報錯了.....

   我們也知道,在結構中還可以定義屬性,所以有童鞋就這樣寫啦.看下面代碼.

   

   這個錯誤,仍然提示我們在構造函數(shù)中沒有為所有的字段賦值,這是很多童鞋遇到的問題,誒,不是要在構造函數(shù)中為所有的字段賦值么?我現(xiàn)在賦值了啊,。為什么還是提示沒有賦值呢? 我們在構造函數(shù)中為屬性賦值 而屬性又為字段賦值,為什么這樣就不行呢? 原因很簡單.因為語法要求我們?yōu)樗械淖侄钨x值,雖然這里我們看得出來為屬性賦值其實屬性再把值賦值給字段, 我們說屬性是對字段的操作,但是一定是這樣的嗎?我們完全可以在屬性的set塊里面什么都不寫,如果什么都不寫,那么屬性還是在操作字段嗎? 所以屬性不一定是在操作字段的,在結構體的構造函數(shù)中我們?yōu)閷傩再x值,不認為是在對字段賦值,所以我們在構造函數(shù)中要直接為字段賦值.

  c.創(chuàng)建結構體對象的方式.

   創(chuàng)建結構體對象可以不使用new關鍵字.直接聲明1個變量就可以.但是這樣的話,結構體對象中的字段是沒有初始值的,所以在使用字段之前必須要為這個字段賦值.

   

   原因很簡單.因為聲明的時候就不能給初始值,雖然構造函數(shù)中為對象的字段賦值,但是此種方式創(chuàng)建結構體對象,沒有調(diào)用構造函數(shù),所以必須要程序員在使用之前手動賦值,。下面這樣就可以了.

   

  另外1種創(chuàng)建結構體對象的方式和類一樣,使用new關鍵字來創(chuàng)建,與不使用new關鍵字創(chuàng)建不同的是,通過使用new關鍵字創(chuàng)建結構體對象后,這個結構體對象的字段就已經(jīng)有值了.原因不難理解,new關鍵字調(diào)用了構造函數(shù),而結構體構造函數(shù)要求必須要為所有的字段賦值.

  

  所以,我們不難猜出.結構體的無參數(shù)的構造函數(shù)做了什么事情,在無參數(shù)的構造函數(shù)中為所有的字段賦值,值類型的字段賦值0,給引用類型的字段賦值null.

  d. 結構體不能從另外1個結構或者類繼承,但是可以實現(xiàn)接口.特殊的是.雖然結構不能從別的類或者結構繼承,但是所有的結構都默認從ValueType類繼承,ValueType類再從Object類繼承.所以結構體對象仍然擁有超類Object的成員.看看下面的微軟生成的代碼就知道了.

    

3. 它們之間最大的區(qū)別 是結構體是值類型 類是引用類型.

   結構體是值類型,當其作為1個局部變量的時候,變量是存儲在??臻g中的,其對象的字段直接存儲在這個變量中的.就像下面這樣.

   

   與引用類型的類不一樣,引用類型的變量中存儲的是對象在堆空間中的地址,所以當我們傳遞1個引用類型的變量的時候,其實傳遞的是變量的值(對象的地址) 傳遞完以后 對變量的修改會影響到另外1個變量指向的對象的值.

 

4. 最后 談一下什么時候使用結構,什么使用類.

   我們知道,結構存儲在棧中,而棧有1個特點,就是空間較小,但是訪問速度較快,堆空間較大,但是訪問速度相對較慢.所以當我們描述1個輕量級對象的時候,可以將其定義為結構來提高效率.比如點,矩形,顏色,這些對象是輕量級的對象,因為描述他們,只需要少量的字段,。當描述1個重量級對象的時候,,我們知道類的對象是存儲在堆空間中的,我們就將重量級對象定義為類. 他們都表示可以包含數(shù)據(jù)成員和函數(shù)成員的數(shù)據(jù)結構。與類不同的是,,結構是值類型并且不需要堆分配,。結構類型的變量直接包含結構的數(shù)據(jù),而類類型的變量包含對數(shù)據(jù)的引用(該變量稱為對象),。 struct 類型適合表示如點,、矩形和顏色這樣的輕量對象。盡管可能將一個點表示為類,但結構在某些方案中更有效,。在一些情況下,,結構的成本較低。例如,,如果聲明一個含有 1000 個點對象的數(shù)組,,則將為引用每個對象分配附加的內(nèi)存。所以結構適合表示1個輕量級對象.

   基于另外1個理由我也會使用結構. 我們在變量傳值的時候,我就是希望傳遞對象的拷貝,而不是對象的引用地址,那么這個時候也可以使用結構了.

 

  以上只是個人總結,難免會有些地方有瑕疵,歡迎大家指正,謝謝.!

 

 

   

 

  

 

         

 

    本站是提供個人知識管理的網(wǎng)絡存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導購買等信息,,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,,請點擊一鍵舉報,。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多