1. 主要內容編程
類型的基本概念數組
值類型深刻安全
引用類型深刻框架
值類型與引用類型的比較及應用編程語言
2. 基本概念性能
C#中,變量是值仍是引用僅取決於其數據類型。ui
C#的基本數據類型都以平臺無關的方式來定義,C#的預約義類型並無內置於語言中,而是內置於.NET Framework中。.NET使用通用類型系統(CTS)定義了能夠在中間語言(IL)中使用的預約義數據類型,全部面向.NET的語言都最終被編譯爲 IL,即編譯爲基於CTS類型的代碼,線程
通用類型的系統的功能:3d
例如,在C#中聲明一個int變量時,聲明的其實是CTS中System.Int32的一個實例。這具備重要的意義:指針
int i;
i = 1;
string s;
s = i.ToString();
CLR 支持兩種類型:值類型和引用類型,
C#的全部值類型均隱式派生自System.ValueType:
值類型(Value Type),值類型實例一般分配在線程的堆棧(stack)上,而且不包含任何指向實例數據的指針,由於變量自己就包含了其實例數據
C#有如下一些引用類型:
能夠看出:
2.1內存深刻
2.2.1 內存機制
數據在內存中分配位置取決與該變量的數據類型,上圖可知值類型分配在線程的堆棧上,引用類型則分配在託管堆上,由GC控制回收,如下代碼和圖演示了引用類型和值類型的區別:
private static class ReferenceVsValue {
// Reference type (because of 'class')
private class SomeRef { public Int32 x; }
// Value type (because of 'struct')
private struct SomeVal { public Int32 x; }
public static void Go() {
SomeRef r1 = new SomeRef(); //在堆上分配
SomeVal v1 = new SomeVal(); // 在棧上分配
r1.x = 5; // 提領指針
v1.x = 5; // 在棧修改
Console.WriteLine(r1.x); // 顯示」5」
Console.WriteLine(v1.x); //一樣顯示」5」
// 下圖左半部分反映了執行以上代碼以後的情形
SomeRef r2 = r1; //只複製引用(指針)
SomeVal v2 = v1; // 在棧上分配而且複製成員
r1.x = 8; // r1.x和r2.x都會更改
v1.x = 9; // 只是更改v1.x,不會更改v2.x
Console.WriteLine(r1.x); // 顯示 "8"
Console.WriteLine(r2.x); // 顯示 "8"
Console.WriteLine(v1.x); // 顯示 "9"
Console.WriteLine(v2.x); // 顯示 "5"
//右半部分反映了在執行全部代碼以後的狀況
}
}
圖5-1 圖解代碼執行時的內存分配狀況
SomeVal是用Struct來聲明的,而不是用經常使用的Class,在C#中用Struct聲明的是值類型,每一個變量或者程序都有本身的堆棧,不一樣的變量不能公用一個內存地址所以上圖中SomeRef和SomeVal必定佔用了不一樣的堆棧,變量通過傳遞後,對v1變量改變時,顯然不會影響到v2的數據,能夠看出,堆棧中的v1,v2包含其實際數據,而r1,r2則在堆棧中保存了其實例數據的引用地址,實際的數據保存在託管堆中,所以就有可能不一樣變量保存了 同一地址的數據引用,當從一個引用類型變量傳遞到另一個相同的引用類型變量時,傳遞的是引用地址而不是實際的數據,因此改變一個變量的值會影響到另一個變量的值,值類型與引用類型在內存中的分配是決定其應用不一樣的根本緣由,由此能夠容易的解釋爲何傳遞參數的時候,按值傳遞不會改變形參的值,而按地址傳遞會改變形參的值。
內存分配的幾點:
值類型變量作爲局部變量時,該實例將被建立在堆棧上;而若是值類型變量做爲類型的成員變量時,它將做爲類型實例數據的一部分,同該類型的其餘字段都保存在託管堆上,將在接下來的嵌套結構部分來詳細說明問題。
引用類型變量數據保存在託管堆上,可是根據實例的大小有所區別,以下:若是實例的大小小於85000Byte時,則該實例將建立在GC堆上;而當實例大小大於等於85000byte時,則該實例建立在LOH(Large Object Heap)堆上。
2.2.2嵌套類型
嵌套結構就是在值類型中嵌套定義了引用類型,或者在引用類型變量中嵌套定義了值類型
public class NestedValueinRef
{
//aInt作爲引用類型的一部分將分配在託管堆上
private int aInt;
public NestedValueinRef
{
//aChar則分配在該段代碼的線程棧上
char achar = 'a';
}
} 圖5-2 內存分配圖能夠表示爲:
引用類型嵌套在值類型時,內存的分配狀況爲:該引用類型將做爲值類型的成員變量,堆棧上將保存該成員的引用,而成員的實際數據仍是保存在託管堆中.
public struct NestedRefinValue
{
public MyClass myClass;
public NestedRefinValue
{
myClass.X = 1;
myClass.Y = 2;
}
}
圖5-3 內存分配圖能夠表示爲: