Вопросы о структурах - PullRequest
       10

Вопросы о структурах

7 голосов
/ 20 марта 2009

MSDN говорит, что класс, который будет иметь размер 16 байт или меньше, будет лучше обрабатываться как структура [цитата] .
Почему это так?
Означает ли это, что если структура превышает 16 байтов, она менее эффективна, чем класс, или это то же самое?
Как вы определяете, что ваш класс меньше 16 байт?
Что ограничивает структуру от действия как класс? (кроме запрета на конструкторы без параметров)

Ответы [ 7 ]

6 голосов
/ 20 марта 2009

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

  • Структуры имеют тип значения, классы являются ссылочным типом. Если вы используете 16 байт для общего хранения, вероятно, не стоит создавать ссылки на память (от 4 до 8 байт) для каждого.
  • Когда у вас действительно маленькие объекты, их часто можно поместить в стек IL вместо ссылок на объекты. Это действительно может ускорить некоторый код, поскольку вы устраняете разыменование памяти со стороны вызываемого абонента.
  • Есть немного лишнего "пуха", связанного с классами в IL, и если ваша структура данных очень мала, ни один из этих пухов не будет использован в любом случае, поэтому вам просто не нужен лишний мусор.

Самое важное отличие между структурой и классом заключается в том, что структуры являются типом значения, а классы - ссылочным типом.

3 голосов
/ 20 марта 2009

Под "эффективными" они, вероятно, говорят о количестве памяти, которое требуется для представления класса или структуры.

На 32-битной платформе для выделения объекта требуется минимум 16 байтов. На 64-битной платформе минимальный размер объекта составляет 24 байта. Итак, если вы смотрите на это исключительно по объему используемой памяти, структура, которая содержит менее 16 байтов данных, будет «лучше», чем соответствующий класс.

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

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

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

Проверьте эту ссылку, я нашел ее на одном из ответов в SO сегодня: .NET Type Internals . Вы также можете попробовать поискать в SO и Googling «ссылочные типы против типов значений» для определения различий между структурами и классами.

Что мешает структуре действовать как класс?

Есть много отличий. Например, вы не можете наследовать от структуры.

У вас не может быть виртуальных методов, поэтому вы не можете использовать структуру для реализации интерфейса. Методы экземпляра в структурах могут получить доступ к закрытым полям структуры, но помимо этого они ведут себя во многом как вспомогательные «вспомогательные» функции (для неизменяемых структур им иногда даже не требуется доступ к частным данным). Поэтому я считаю, что они не так «ценны», как методы класса.

0 голосов
/ 21 января 2011

Копирование экземпляра структуры занимает меньше времени, чем создание нового экземпляра класса и копирование данных из старого, но экземпляры класса могут использоваться совместно, а экземпляры структуры - нет. Таким образом, "structvar1 = structvar2" требует копирования нового экземпляра структуры, тогда как "classvar1 = classvar2" позволяет classvar1 и classvar2 ссылаться на один и тот же экземпляр структуры (без необходимости создания нового).

Код для управления созданием новых экземпляров структуры оптимизирован для размеров до 16 байт. Большие структуры обрабатываются менее эффективно. Структуры выигрывают в тех случаях, когда каждая переменная, которая содержит структуру, будет содержать независимый экземпляр (т. Е. Нет никаких оснований ожидать, что какие-то две конкретные переменные будут содержать идентичные экземпляры); они не слишком выигрывают (если вообще выигрывают) в тех случаях, когда многие переменные могут содержать один и тот же экземпляр.

0 голосов
/ 20 марта 2009

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

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

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

0 голосов
/ 20 марта 2009

Это связано с тем, что CLR обрабатывает структуры и классы. Структуры являются типами значений, что означает, что они живут в стеке, а не в управляемой куче. Хорошее эмпирическое правило - сохранять структуры небольшими, потому что как только вы начнете передавать их в качестве аргументов метода, вы будете подвергаться накладным расходам, поскольку структуры копируются полностью при передаче в метод.

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

Лучший способ определить размер вашего класса - это общее количество байтов, необходимое всем членам вашего класса, плюс дополнительные 8 байтов для служебных данных CLR (индекс блока синхронизации и ссылка на тип объект).

0 голосов
/ 20 марта 2009

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

Об ограничениях: вы не можете присвоить ему значение NULL (хотя вы можете использовать Nullable <>), и вам нужно сразу его инициализировать.

...