Вопрос

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

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

Решение

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

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

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

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

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

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

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

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

Проверьте эту ссылку, я нашел ее в одном из ответов в SO today: Внутренние компоненты .NET-типа.Вы также можете попробовать выполнить поиск по SO и поискать в Google "ссылочные типы против типов значений" для определения различий между структурами и классами.

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

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

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

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

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

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

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

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

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

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

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

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

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

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