2011-02-02 98 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);