Struct vs Class для долгоживущих объектов - PullRequest
15 голосов
/ 04 марта 2009

Когда вам нужно иметь очень маленькие объекты, скажем, которые содержат 2 свойства float, и у вас будут миллионы из них, которые не будут "уничтожены" сразу, структуры лучше или классы?

Как и в xna в качестве библиотеки, есть point3s и т. Д. Как структуры, но если вам нужно долго удерживать эти значения, не создаст ли это угрозу для производительности?

Ответы [ 6 ]

34 голосов
/ 04 марта 2009

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

Несколько советов:

:: Структура не должна быть больше 16 байт, иначе вы потеряете преимущества в производительности.

:: Сделать структуру неизменной. Это делает использование более понятным.

Пример:

public struct Point3D {

   public float X { get; private set; }
   public float Y { get; private set; }
   public float Z { get; private set; }

   public Point3D(float x, float y, float z) {
      X = x;
      Y = y;
      Z = z;
   }

   public Point3D Invert() {
      return new Point3D(-X, -Y, -Z);
   }

}
5 голосов
/ 04 марта 2009

Ответ зависит от того, где будут храниться объекты / значения. Если они должны храниться в нетипизированной коллекции, такой как ArrayList, тогда вы в конечном итоге их упаковываете. Бокс создает объектную оболочку для структуры, и его размер такой же, как и у объекта класса. С другой стороны, если вы используете типизированный массив, такой как T [] или List, то при использовании структур будут храниться только фактические данные для каждого элемента, занимающего только всю коллекцию, а не его элементы.

Таким образом, структуры более эффективны для использования в массивах T [].

2 голосов
/ 04 марта 2009

Как правило, большие массивы несвязанных (то есть неразделенных) данных одного и того же типа лучше всего хранить в структурах производительности, так как вы уменьшаете количество косвенных ссылок. (См. Также когда ответят ). Точная разница в производительности между классом и структурой зависит от вашего использования. (Например, в операциях вы обращаетесь только к частям структуры? Много ли у вас временных копий? Если структура небольшая, ее всегда лучше использовать, но если она большая, создание временных копий может замедлить работу. чтобы сделать его неизменным, вам придется всегда копировать все это, чтобы изменить значение.)

Если сомневаешься, измерить.

Поскольку вас интересуют возможные долгосрочные эффекты, которые могут не проявиться при таком измерении, имейте в виду, что такие массивы, скорее всего, хранятся в куче больших объектов и должны использоваться повторно вместо уничтожения и перераспределения , (см. CRL Наизнанку: обнаружена куча больших объектов .)

При передаче структур большого размера в вызовах может потребоваться передать их с аргументом ref, чтобы избежать копирования.

2 голосов
/ 04 марта 2009

Struct кажется подходящим для этого приложения.

Имейте в виду, что "необходимость хранить эти значения S" подразумевает их хранение где-то в куче, вероятно, в поле массива экземпляра класса.

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

Использование класса для миллионов этих типов данных, вероятно, будет дорого из-за объема разыменования, который, вероятно, будет иметь место для операций с этим типом.

2 голосов
/ 04 марта 2009

Большая проблема в том, выделена ли память в стеке или в куче. Структуры помещаются в стек по умолчанию, и стек обычно намного более ограничен с точки зрения пространства. Так что создание целой связки структур может быть проблемой.

На практике, правда, я не думаю, что это так уж важно. Если у вас их так много, скорее всего, они где-то в экземпляре класса (в куче).

1 голос
/ 04 марта 2009

Типы значений (структура) хороши для типов, которые часто не выделяются в куче, то есть они в основном содержатся в другом ссылочном типе или типе значения.

Пример Vector3, который вы привели, является прекрасным примером. У вас редко будет висящий Vector3 в куче, в большинстве случаев он будет содержаться в типе, который сам находится в куче, или использоваться как локальная переменная, в этом случае он будет размещен в стеке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...