資料:《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;
}