.NET(C#):理解實值型別/參考型別,裝箱/拆箱,Object類

來源:互聯網
上載者:User

裝箱/拆箱,實值型別/參考型別 和 Object類,這些都是.NET程式員人人皆知且人人都應該掌握的概念。大多數人都對他們非常瞭解,可是和一些同行們交流時我發現一些細節其實很多人並不瞭解,尤其是它們結合討論的情景,本文通過一些代碼來闡述一些我知道的概念。

 

目錄

  • 代碼1:Object.Equals
  • 代碼2:Object.ReferenceEquals
  • 代碼3:再強化一下理解
  • 代碼4:問候了Equals,我們再看看==
  • 代碼5:神奇的String
  • 代碼6:欄位和屬性
  • 代碼7:MemberwiseClone()

 

 

 

返回目錄

代碼1:Object.Equals

考慮下面代碼的結果:

Console.WriteLine(Object.Equals(1, 1));

Console.WriteLine(Object.Equals(1, (byte)1));

 

答案:True, False

首先Object.Equals參數是兩個object,所以1(實值型別)會被裝箱成參考型別,這會使CLR在託管堆中建立兩個全新的Object對象,然後Object.Equals先判斷兩個object是否有null,沒有則調用Object的對象方法Equals,而由於1是實值型別,實值型別改寫Object.Equals並進行位元比較,最終由於object1的位元值完全等於object2的位元值第一句True,第二句很顯然Int和Byte記憶體大小不一樣,位元比較不會成功。

 

 

返回目錄

代碼2:Object.ReferenceEquals

代碼2:Object.ReferenceEquals

Console.WriteLine(Object.ReferenceEquals(1, 1));

 

答案:False

同樣,Object.ReferenceEquals參數是兩個object,所以CLR會在託管堆中建立兩個object來分別裝Int值,但Object.ReferenceEquals的函數就是判斷兩個引用的是否指向同一個在託管堆的空間對象,這裡當然是False了。

 

返回目錄

代碼3:再強化一下理解

下面代碼,如果MyType是class或struct時,分別會輸出什嗎?

struct/class MyType

{

    public int Data;

}

class Program

{

    static void Main(string[] args)

    {

        MyType s1 = new MyType();

        MyType s2 = new MyType();

        s1.Data = s2.Data = 1990;

 

        Console.WriteLine(Object.Equals(s1, s2));

    }

}

 

答案:

struct輸出:True

class輸出:False

這個為了強化下理解,原理和上面的一樣,實值型別和參考型別針對Object.Equals的執行是不一樣的 

 

 

返回目錄

代碼4:問候了Equals,我們再看看==

下面代碼輸出什嗎?

struct MyType

{

    public int Data;

}

class Program

{

    static void Main(string[] args)

    {

        MyType s1 = new MyType();

        MyType s2 = new MyType();

        s1.Data = s2.Data = 1990;

        Console.WriteLine(s1 == s2);

    }

}

 

如果MyType是class,那麼結果所有人會知道是False,那如果MyType是struct,結果是?……結果是編譯錯誤,是的,實值型別中的使用者自訂結構體預設==運算子是不被預先重載的,但是參考型別,枚舉,原始實值型別的==有。

 

 

返回目錄

代碼5:神奇的String

下面輸出結果?

string a = "aaa";

string b = "aaa";

Console.WriteLine(Object.Equals(a, b));

Console.WriteLine(Object.ReferenceEquals(a, b));

Console.WriteLine(a == b);

Console.WriteLine((object)a == b);

//這句VS會提示警告:

//Possible unintended reference comparison; to get a value comparison,

//cast the left hand side to type 'string'

 

答案:都是True,但True的方式不一樣,呵呵,我們一句一句分析

第一句: 調用a.Equals(b),String類的執行是字串比較,true

第二句:注意這裡不進行字串比較,這裡是判斷兩個引用是不是指向同一個對象,因為Object.ReferenceEquals參數是兩個object,但是.NET中相同的字串(編譯器可預知判斷的)CLR會確保它們只向同一個記憶體空間,這個又稱字串的Interning。

第三句:直接調用String的重載==,字串比較。

第四句:調用參考型別(Object)的重載==,其實等於調用Object.ReferenceEquals。參考第二句,這裡Visual Studio提示警告也驗證了第二句的結論,這裡不會進行字串比較,而是判斷兩個引用是否指向同一片記憶體空間對象。  

 

 

返回目錄

代碼6:欄位和屬性

考慮如果Point是class或struct下面程式的結果?

struct/class Point

{

    public int X, Y;

}

 

class MyCls

{

    public Point PField;

    public Point PProperty { get; set; }

}

 

class Program

{

    static void Main()

    {

        MyCls cls = new MyCls();

        cls.PField.X = 3;

        cls.PProperty.X = 3;

    }

}

 

答案:如果是Point是struct(即實值型別),cls.PField.X會賦值成功,而cls.FProperty.X不會賦值成功(其實根本無法編譯成功),因為屬性本質上就是函數調用,這裡PProperty返回一個實值型別的拷貝,編輯這個拷貝的內部欄位是沒有意義的。

如果Point是class(即參考型別),會拋出NullReference異常,因為類內的參考型別預設CLR不為他們分配空間的,所以他們保持預設值(null)。

 

 

 

返回目錄

代碼7:MemberwiseClone()

MemberwiseClone()是一個非常有用的函數,但很多人不會用它,它不是引用的直接拷貝,而是將成員欄位進行複製,如果成員是實值型別,那麼將進行深層拷貝,如果是參考型別,那麼只拷貝引用指標(前後兩個引用指向託管堆中的同一份空間)。

考慮下面代碼輸出?

class a

{

    public object obj;

    public object ShadowCopy()

    {

        return MemberwiseClone();

    }

}

class Program

{

    static void Main(string[] args)

    {

        a oa = new a() { obj = new object() };

        a ob = oa;

        a oc = (a)oa.ShadowCopy();

 

        oa.obj = null;

        Console.WriteLine(ob.obj == null);

        Console.WriteLine(oc.obj == null);

    }

}

 

答案:True, False

ob和oa指向同一個對象,所以oa變了,ob也變,oc是oa的MemberwiseClone的結果,oa的改變僅將自己的引用改成null。而oc沒變,oc的成員引用還指向原來的位置。  

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.