[譯]分辨差別 -- 第三部分: fixed 和 fixed

iDotNetSpace發表於2009-10-13

譯自Eric Lippert's Blog, 原文: http://blogs.msdn.com/ericlippert/archive/2009/08/27/what-s-the-difference-between-fixed-and-fixed.aspx

    某天我收到一封這樣開頭的郵件:

    我有一個關於C# 固定大小的緩衝區的問題:

    unsafe struct FixedBuffer { public fixed int buffer[100]; }

    現在把緩衝區宣告為固定的,它就是不可移動的...

    看到這個問題我的心都碎了。如果語言細節設計容易造成誤解,那麼上面所遇到的情況只是極為不幸的時刻之一。

    當在非安全的程式碼中對託管物件使用指標演算法時,你要確保垃圾回收器不會把你正需要的記憶體移掉。當你正在用指標操作某個物件的時候,如果另外一個執行緒進行了資源回收,那麼這個指標將完全混亂。因此,C#把變數分為“固定的”和“可變的”。如果你想要將指標應用到一個可移動的物件上,你可以使用“fixed”關鍵字來宣告“這個區域性變數是不能被垃圾回收器移動的”。當回收行為發生時,垃圾回收器要為那些正在進行的呼叫檢視所有區域性變數(那些被用到的變數需要保留);如果回收器看到某變數被標為“fixed”,它不會移動這樣的變數,即使這會造成託管堆碎片(由此也看出讓這樣的變數固定的時間儘可能少是很重要的)。所以典型地,我們用“fixed”代表固定在某個地方。

    但是在這封郵件中的“fixed”並不是這個意思,這裡的意思是將此問題中的buffer的大小固定為容納100個int變數,本質上講,這和在結構中建立100個int型別的成員是一樣的。

    明顯地,我們經常使用相同的關鍵字來表示概念上相同的東西。比如,在C#中我們經常用不同的方式使用關鍵字“internal”,但是所有的“internal”表示的意義都是一樣的。它只是用來表示“一些實體的訪問許可權在同一程式集的程式碼中是不受限制的”。

    某些時候我們也用相同的關鍵字來表示概念上完全不同的東西,這要依賴於使用者使用的上下文環境來確定它代表的意思。比如:

var results = from c in customers where c.City == "London" select c;

class C where T : IComparable

    很明顯“where”使用於兩種完全不同的方式:建立查詢語句中的篩選從句,和宣告一個泛型引數的約束型別。

    如果一個關鍵字用於兩種不同的意義但是這個區別非常細微,就像我們上面舉到的例子,這會使人們碰到困難。那個使用者的郵件將會繼續問上一大堆的問題,但是這些問題都是基於一個不正確的假設——一個固定大小的緩衝區會自動地固定在記憶體中的某一位置。

    這隻能說這是一個不好的術語的混用:“固定大小”和“固定位置”都是使用“fixed”,但是使用的方式不同,這是很讓人頭疼的事情。然而它們之間的關聯比這還要複雜:只有當某固定大小的緩衝區的容器被固定在某塊記憶體區,你才能安全地訪問儲存在該緩衝區中的資料。在這個問題中,這兩個概念具有很強的相關性,但是並不完全相同。

    一方面,為了減少混亂,我們可以使用兩個不同的關鍵字,比如說“pinned”和“fixed”。但是另一方面,“fixed”的所有用法只在非安全程式碼中才可用。對於非安全的碼的所有特性,一個關鍵的前提假設就是:如果你想在C#中使用非安全程式碼,那麼你肯定已經是一個完全理解CLR中記憶體管理的程式設計專家。這也是為什麼我們讓你在程式碼中標明“unsafe”的原因;它表明你關閉了安全系統並且知道自己在做什麼。

    在C#中可以多用的一些重要的關鍵字:fixed, into, partial, out, in, new, delegate, where, using, class, struct, true, false, base, this, event, return和void都至少包含兩種以上不同的意思。大部分的在位於特定上下文中的時候都很清楚,但是至少前三個——fixed, into和partial——已經造成了很多的困擾,我已經收到了很多困惑的使用者關於它們使用區別的問題。我接下來會看一下“into”和“partial”。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-616445/,如需轉載,請註明出處,否則將追究法律責任。

相關文章