2011-02-02 100 views
0

首先,我們的環境的基本信息:我們在Win7-x64上使用c#.net 4.0,目標是32位。我們有一個預分配的大數組。在一個函數中,我們想返回一個指向這個數組中任意點的指針,這樣調用函數就可以知道在哪裏寫入。例:如何獲取指向c中數組中間的指針#

class SomeClass { 
    void function_that_uses_the_array() { 
     Byte [] whereToWrite = getEmptyPtrLocation(1200); 
     Array.Copy(sourceArray, whereToWrite, ...); 
    } 
} 

class DataProvider { 
    int MAX_SIZE = 1024*1024*64; 
    Byte [] dataArray = new Byte[MAX_SIZE]; 
    int emptyPtr=0; 
    Byte[] getEmptyPtrLocation(int requestedBytes) { 
     int ref = emptyPtr; 
     emptyPtr += requestedBytes; 
     return dataArray[ref]; 
    } 
} 

本質上,我們要預先分配的存儲器一大塊,並且該存儲器塊的儲備任意長度的部分,並讓其他一些類/函數使用的存儲器的部分。

在上例中,getEmptyPtrLocation函數不正確;它被聲明爲返回字節[],但試圖返回單個字節值。

感謝

+3

爲什麼要那樣做? – Femaref 2011-02-02 15:09:18

回答

4

正如其他人所說,你不能在C#中做到這一點 - 一般你不應該做任何喜歡它。該系統的工作 - 把垃圾收集等

說了這麼多,如果你想要做類似的事情的優勢,你可以相信你的客戶不要超限分配給他們的插槽,你可以讓你的方法返回ArraySegment<byte>而不是byte[]。這將代表「數組的一部分」。很明顯,.NET中的大多數方法都不使用ArraySegment<T> - 但是您可能會使用寫入擴展方法,將其用作您想要使用的一些更常見操作的目標。

2

沒有進入非託管代碼,你不能返回一個指針在C#中的數組中,所有你能做的就是要在其中輸入數據,返回數組的索引。

3

這是C#沒有C++ - 你真的在這裏對付垃圾收集器。內存分配在C#中通常非常快,也不會受到內存碎片的影響,這是在C++中預先分配的其他主要原因之一。

話雖如此,而你仍然想這樣做,我只會使用數組索引和長度,所以你可以使用Array.Copy寫在那個位置。

編輯:

正如其他人所指出ArraySegment<T>更好地滿足您的需求:它限制了消費者只是他的陣列的切片,它不要求更新的內容之前分配一個單獨的數組在原始數組中(由ArraySegment表示)。

+0

同意這個觀點(不應該這樣做),不同意使用Array.Copy。這分配新的內存,它不返回數組的一個子集。從MSDN:http://msdn.microsoft.com/en-us/library/k4yx47a1.aspx – 2011-02-02 15:20:32

+0

@Chris:同意 - Array.Copy將要求使用它的類在將其複製到目標緩衝區之前分配它們自己的緩衝區,他們也可以訪問完整的數組 - 所以是`ArraySegment`會更好。 – BrokenGlass 2011-02-02 15:54:55

1

如果你必須做到這一點,你的選擇包括返回ArraySegment(如Jon Skeet指出)或使用Streams。您可以使用this構造函數返回作爲數組子集的MemoryStream。您將需要處理所有的內存讀取和寫入操作,但不是作爲偏移操作。

1

很舊的帖子,但我有一個簡單的解決方案。我發現這個問題有很多答案,比如「你不應該」。如果有辦法做某事,爲什麼不使用它?

但是,這一邊,你可以使用下面的

int[] array = new int[1337]; 
position = 69; 
void* pointer = (void*)Marshal.UnsafeAddrOfPinnedArrayElement(array, position);