Как определить размер неуправляемого массива в C #? - PullRequest
1 голос
/ 26 ноября 2011

Я пытаюсь оптимизировать некоторый код, где у меня есть большое количество массивов, содержащих структуры разного размера, но основанные на том же интерфейсе.В некоторых случаях структуры имеют больший размер и содержат больше данных, в других случаях они являются небольшими структурами, а в других случаях я бы предпочел оставить значение NULL в качестве значения для экономии памяти.

Мой первый вопрос.Это хорошая идея сделать что-то подобное?Ранее у меня был массив моей полной структуры данных, но при тестировании, смешивая ее, я практически смог бы сэкономить много памяти.Есть ли какие-либо другие недостатки?

Я пробовал разные вещи, и это выглядит довольно неплохо при создании массива общего интерфейса, но я не уверен, что проверяю размермассив правильно.

Чтобы упростить пример совсем немного.Но здесь я добавляю различные структуры в массив.Но я не могу определить размер, используя традиционный метод Marshal.SizeOf.Было бы правильно просто перебрать коллекцию и посчитать sizeof для каждого значения в коллекции?

IComparable[] myCollection = new IComparable[1000];
myCollection[0] = null;
myCollection[1] = (int)1;
myCollection[2] = "helloo world";
myCollection[3] = long.MaxValue;

System.Runtime.InteropServices.Marshal.SizeOf(myCollection);

Последняя строка выдаст это исключение:

Type 'System.IComparable[]' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.

Извините за длинныйpost:

  1. Это оптимальное и удобное решение?
  2. Как определить размер моего массива?

Ответы [ 2 ]

1 голос
/ 05 января 2012

Я могу ошибаться, но мне кажется, что ваш массив IComparable [] является управляемым массивом? Если это так, то вы можете использовать этот код, чтобы получить длину

int arrayLength = myCollection.Length;

Если вы выполняете взаимодействие между платформами между C # и C ++, тогда ответ на заголовок вашего вопроса «Можно ли найти длину неуправляемого массива» - нет, это невозможно. Сигнатуры функций с массивами в C ++ / C имеют тенденцию следовать следующей схеме

void doSomeWorkOnArrayUnmanaged(int * myUnmanagedArray, int length) 
{
    // Do work ...
} 

В .NET сам массив является типом, который имеет некоторую базовую информацию, такую ​​как его размер, тип времени выполнения и т. Д. Поэтому мы можем использовать это

void DoSomeWorkOnManagedArray(int [] myManagedArray) 
{
    int length = myManagedArray.Length; 
    // Do work ...
} 

Всякий раз, когда вы используете платформу для взаимодействия между C # и C ++, вам нужно будет передать длину массива в принимающую функцию, а также закрепить массив (но это другая тема).

Это отвечает на ваш вопрос? Если нет, то, пожалуйста, уточните

0 голосов
/ 05 января 2012

Оптимальность всегда зависит от ваших требований.Если вам действительно нужно хранить много элементов разных классов / структур, ваше решение полностью жизнеспособно.

Однако я предполагаю, что ваши ожидания в отношении структуры данных могут вводить в заблуждение: элементы массива для определения имеют одинаковый размер.Это даже верно в вашем случае: ваш массив не хранит сами элементы, но ссылается на (указатели) на них.Элементы расположены где-то в куче виртуальных машин.Таким образом, ваша структура данных на самом деле выглядит следующим образом: это массив из 1000 указателей, каждый указатель указывает на некоторые данные.Размер каждого конкретного элемента может, конечно, различаться.

Это приводит к следующему вопросу: размер вашего массива.Что вы собираетесь делать с размером?Вам нужно знать, сколько байтов выделить при сериализации данных в какое-либо постоянное хранилище?Это зависит от формата сериализации ... Или вам нужна только приблизительная оценка того, сколько памяти использует ваша структура?В последнем случае вам необходимо учитывать сам массив и размер каждого конкретного элемента.Массив, который вы дали в вашем примере, потребляет примерно в 1000 раз больше размера ссылки (должен быть 4 байта на 32-битной машине и 8 байтов на 64-битной машине).Чтобы вычислить размеры каждого элемента, вы действительно можете перебирать массив и суммировать размер отдельных элементов.Обратите внимание, что это только приблизительная оценка: виртуальная машина добавляет некоторые накладные расходы на управление памятью, которые трудно точно определить ...

...