C#值類型和引用類型


資料:《Learning hard C#學習筆記》李志

值類型:

  1.包含類型:

    簡單類型:int,long,short,sbyte,uint,ulong,ushort,byte,char,float,double,decimal,bool

    枚舉類型:enum

    結構體類型:struct

    

引用類型:

  1.包含類型:

     類類型:string,Console類和自定義類

    數組類型:一維數組,多維數組

    接口類型:interface

    委托類型:delegate

 

 

值類型和引用類型的區別:

  1.值類型分配在線程堆棧上(管理由操作系統負責),引用類型分配在托管堆上(管理由垃圾回收器GC負責)。管理指內存空間的分配和釋放

    1)變量本身是存儲在堆棧上的(無論是值類型變量還是引用類型變量)

    2)但是對於實際數據:引用類型存在托管堆上,值類型存在堆棧

  2.值類型繼承自valueType,valueType繼承自System.Object;引用類型直接繼承自System.Object

  3.值類型在作用域內結束時,會被操作系統自釋放,減少托管堆壓力;引用類型則靠GC。因此值類型在性能上由優勢

  4.值類型是密封的,不能作為基類。引用類型一般具有繼承性

  5.值類型不能為null,默認初始化為該類型的默認值;引用類型默認初始化為null

  6.值類型作為參數傳遞時,不影響本身。引用類型作為參數傳遞時,會改變最終該變量的值

 

裝箱:值類型轉為引用類型

  步驟:

    1)內存分配:在托管堆分配內存空間

    2)實際數據的復制:將值類型的數據復制到新分配的內存中

    3)地址返回

拆箱:引用類型轉為值類型

  步驟:

    1)檢查實例:引用類型是否為Null?不為Null那和拆箱后的類型是否是同一類型

    2)地址返回

    3)數據復制:堆數據復制到棧

裝箱和拆箱都會對數據進行復制,所以會影響性能。最好使用泛型編程

 

在方法的形參操作中,值類型調用方法后不會更改原數據的值,引用類型則會更改數據的值。但是引用類型的string是具有不可變性的,例如在形參傳遞string類型的數據,該方式通過重新分配一個新的空間存儲新數據實現的。

 

無論值類型還是引用類型,都可以通過ref,out關鍵字實現引用傳遞。這樣就解決了返回多個值問題

 

 public IActionResult Index()
        {
            ValueTypeAndRefType newType = new ValueTypeAndRefType();
            int age = 6;
            newType.changeByValue(ref age);//age:100
            string name = "zs";
            newType.changeByRef(ref name);
            ViewBag.Cat66 = name;//name:abc 實際上因為string不可變,也是開辟了新的空間,只是把name的指向改成了新的變量指向
        
            return View();
        }

 

    public class ValueTypeAndRefType //類是引用類型,通過調用類,再去改里面的值,那么該實例化類的該值也會被改掉
    {
        public int valueType = 3;

        public int method()
        {
            int age = 10;//堆棧

            isValueType(age);
            return age; //10
        }

        public void isValueType(int val)
        {
            val = 20;
        }

        public void changeByValue(ref int val)
        {
            val = 100;
        }
        public void changeByRef(ref string val)
        {
            val = "abc";
        }
    }  

  

 

ref和out的區別:

    ref的參數必須在方法外初始化,out的參數在方法內必須賦值

重載是不看ref和out的,背后的編譯是一樣的

 

 

is和as類型轉換:(轉換類型最好通過is,as判斷,因為強制轉換會拋出異常)

  is用來判斷類型是否可以轉換(引用類型轉換,裝箱,拆箱)

  as是兩個引用之間進行轉換,成功則賦值,不成功則返回null

 

            //is,as
            object o = new object();
            if (o is int)//引用類型轉換,裝箱,拆箱
            {
                ViewBag.Cat66 = "yes";
            }
            else
            {
                ViewBag.Cat66 = "no";
            }

            string n = null;
            object m = n as object;//兩個引用之間進行轉換
            if (m == null)
            {
                ViewBag.Cat66 = "no";
            }
            else
            {
                ViewBag.Cat66 = m;
            }

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM