Вопрос

First, basic info on our environment: We're using c# .net 4.0, on Win7-x64, targeting 32-bit.

We have a preallocated -large- array. In a function, we would like to return a pointer to an arbitrary point in this array, so that the calling function can know where to write. Ex:

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];
    }
}

Essentially, we want to preallocate a big chunk of memory, and reserve arbitrary length portions of this memory block and let some other class/function to use that portion of memory.

In the above example, getEmptyPtrLocation function is incorrect; it is declared as returning Byte[], but attempting to return a single byte value.

Thanks

Это было полезно?

Решение

As others have said, you can't do this in C# - and generally you shouldn't do anything like it. Work with the system - take advantage of the garbage collector etc.

Having said that, if you want to do something similar and you can trust your clients not to overrun their allocated slot, you could make your method return ArraySegment<byte> instead of byte[]. That would represent "part of an array". Obviously most of the methods in .NET don't use ArraySegment<T> - but you could potentially write extension methods using it as the target for some of the more common operations that you want to use.

Другие советы

This is C# not C++ - you are truly working against the garbage collector here. Memory allocation is generally very fast in C#, also it doesn't suffer from memory fragmentation one of the other main reasons to pre-allocate in C++.

Having said that and you still want to do it I would just use the array index and length, so you can use Array.Copy to write at that position.

Edit:

As others have pointed out the ArraySegment<T> fits your needs better: it limits the consumer to just his slice of the array and it doesn't require to allocate a separate array before updating the content in the original array (as represented by the ArraySegment).

Without going into unmanaged code, you can't return a pointer to the middle of the array in C#, all you can do is return the array index where you want to enter the data.

Quite old post this is but I have an easy solution. I see that this question has lot's of answers like "you shouldn't". If there is a method to do something, why not use it?

But that aside, you can use the following

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

If you must do this, your options include returning an ArraySegment (as Jon Skeet pointed out), or using Streams. You can return a MemoryStream that is a subset of an array using this constructor. You will need to handle all of your memory reads and writes as stream operations however, not as offset operations.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top