Как получить указатель на середину массива в c # - PullRequest
0 голосов
/ 02 февраля 2011

Во-первых, базовая информация о нашей среде: мы используем c # .net 4.0 на Win7-x64 для 32-битного.

У нас есть предварительно выделенный массив -large-.В функции мы хотели бы вернуть указатель на произвольную точку в этом массиве, чтобы вызывающая функция могла знать, куда писать.Пример:

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 неверна;он объявляется как возвращающий Byte [], но пытающийся вернуть одно байтовое значение.

Спасибо

Ответы [ 5 ]

4 голосов
/ 02 февраля 2011

Как уже говорили другие, вы не можете делать это в C # - и вообще вы не должны делать что-то подобное. Работайте с системой - воспользуйтесь сборщиком мусора и т. Д.

Сказав, что, если вы хотите сделать что-то похожее и , вы можете доверять своим клиентам, чтобы они не превышали выделенный им слот, вы можете заставить свой метод возвращать ArraySegment<byte> вместо byte[]. Это будет представлять «часть массива». Очевидно, что большинство методов в .NET не используют ArraySegment<T> - но вы могли бы потенциально написать методы расширения, используя его в качестве цели для некоторых из наиболее распространенных операций, которые вы хотите использовать.

3 голосов
/ 02 февраля 2011

Это C #, а не C ++ - здесь вы действительно работаете против сборщика мусора. Распределение памяти, как правило, очень быстро в C #, и оно не страдает от фрагментации памяти, что является одной из других основных причин для предварительного выделения в C ++.

Сказав это, и вы все еще хотите это сделать, я бы просто использовал индекс и длину массива, чтобы вы могли использовать Array.Copy для записи в этой позиции.

Edit:

Как уже отмечали другие, ArraySegment<T> лучше соответствует вашим потребностям: он ограничивает потребителя только его частью массива и не требует выделения отдельного массива перед обновлением содержимого в исходном массиве (как представлено по ArraySegment).

2 голосов
/ 02 февраля 2011

Не вдаваясь в неуправляемый код, вы не можете вернуть указатель на середину массива в C #, все, что вы можете сделать, это вернуть индекс массива, в который вы хотите ввести данные.

1 голос
/ 08 марта 2013

Довольно старый пост, но у меня есть простое решение.Я вижу, что этот вопрос имеет много ответов, как "вы не должны".Если есть способ что-то сделать, почему бы не использовать его?

Но кроме этого, вы можете использовать следующее

int[] array = new int[1337];
position = 69;
void* pointer = (void*)Marshal.UnsafeAddrOfPinnedArrayElement(array, position);
1 голос
/ 02 февраля 2011

Если вы должны сделать это, ваши варианты включают возврат ArraySegment (как указал Джон Скит) или использование Streams.Вы можете вернуть MemoryStream, который является подмножеством массива, используя этот конструктор.Однако вам нужно будет обрабатывать все операции чтения и записи в памяти как потоковые операции, а не как операции смещения.

...