1.爲什麼要有unsafe程序員
也許是爲了實現CLR類型安全的目標吧,默認狀況下,C#沒有提供指針的使用算法,可是有些狀況下也可能須要指針這樣直接訪問內存的東西(雖然目前我尚未用過),可是有時候程序員很是清楚程序的運行情況,須要使用指針直接訪問內存以便於提升性能或者調試、監控程序運行的內存的使用情況,以便於採起相應的措施。還有一些狀況是當咱們須要調用外面DLL中的函數又不能使用DllImport 時,也須要指針來傳遞這些函數。算法
2.unsafe 的定義安全
MSDN:unsafe 關鍵字表示不安全上下文,該上下文是任何涉及指針的操做所必需的。函數
其實,意思就是要使用指針前,請用unsafe 聲明下,可使類、方法,成員,類全局變量和代碼段,但不能修飾成員函數內部的局部變量,具體爲何不清楚,還望大神指點。性能
在使用unsafe以前,咱們必須先看一段MSDN的話:在公共語言運行時 (CLR) 中,不安全代碼是指沒法驗證的代碼。 C# 中的不安全代碼不必定是危險的;只是其安全性沒法由 CLR 進行驗證的代碼。 所以,CLR 只對在徹底受信任的程序集中的不安全代碼執行操做。 若是使用不安全代碼,由您負責確保您的代碼不會引發安全風險或指針錯誤。操作系統
所以,咱們在運行unsafe 代碼是要在項目屬性-生成選項裏配置下"容許運行不安全代碼"。先看下簡單的例子:指針
unsafe static void ChangeValue(int* pData)
{
*pData = 200; //修改所在地址值
}調試
unsafe static void Main()
{
int data = 100;
Console.WriteLine("原始值: {0}", data);
ChangeValue(&data); //取data地址並傳遞
Console.WriteLine("改變地址後: {0}", data);內存
Console.ReadLine();
}it
程序輸出: 原始值:100 ; 修改地址後:200
三、引入fixed
當咱們討論fixed的時候,不得不先了解下,託管代碼和非託管代碼,所謂託管代碼就是由CLR去執行的代碼而不是操做系統去執行的代碼,而非託管代碼就是繞過CLR,由操做系統直接執行,它有本身的垃圾回收、類型安全檢查等服務。
而不安全代碼就是容許本身使用指針訪問內存,但同時又要使用CLR提供的垃圾回收機制、類型安全檢查等服務,有的資料認爲是介於CLR和非託管代碼之間的一種代碼運行機制,也能夠理解。
正由於如此,咱們自定義的指針地址就有可能被CLR垃圾回收機制從新調整位置,因此就引入了fixed ,MSDN對fixed的解釋是:fixed 語句設置指向託管變量的指針,並在執行該語句期間"固定"此變量。這樣就能夠防止變量的重定位。
看下代碼的演示:
class PointerDemo{ public int x, y;}class Program{ unsafe static void ChangeValue(int* x, int* y) { *x = 200; //修改所在地址值 *y = 300; } unsafe static void Main() { var obj = new PointerDemo(); Console.WriteLine("原始值: {0}, {1}", obj.x, obj.y); fixed (int* n = &obj.x) { fixed (int* p = &obj.y) { ChangeValue(n, p); //取data地址並傳遞 } } Console.WriteLine("改變地址後: {0}, {1}", obj.x, obj.y); Console.ReadLine(); }}