"Накладные расходы" класса vs Structure в С#?

Я делаю курс 3354 (Реализация системных типов и интерфейсов в .NET Framework 2.0), и сказано, что для простых классов с переменными и функциями членов лучше использовать структуру, чем класс из-за накладных расходов.

Я никогда не слышал об этом, какова справедливость этого заявления?

Ответы

Ответ 1

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

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

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

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

Ответ 2

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

В MSDN есть страница выбор между классами и структурами.

Резюме:

Не определяйте структуру, если тип имеет все следующие характеристики:

  • Он логически представляет одно значение, подобное примитивным типам (целое, двойное и т.д.).
  • У него размер экземпляра меньше 16 байт.
  • Это неизменный.
  • Его не нужно часто вставлять в бокс.

Иногда может быть случай, когда тип действительно должен быть классом, но вам нужно, чтобы он был структурой по соображениям производительности. Это редко, и вы должны убедиться, что знаете, что делаете, прежде чем идти по этому маршруту. Это может быть особенно опасно, если вы нарушаете руководство по неизменности для структур. Mutable structs может вести себя так, как это обычно бывает ожидать большинству программистов.

Ответ 3

Когда С# находился в состоянии бета-тестирования, меня рассматривали на демонстрации разницы между классом и структурой. Разработчики создали средство просмотра Mandelbrot set, которое обрабатывает множество сложных чисел для достижения своего результата. В первом случае они запускали код с комплексными числами, представленными как класс с полем Real и Imaginary. Затем они сменили слово class на struct и перекомпилировали. Разница в производительности была огромной.

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

Ответ 4

Вы собираетесь использовать класс примерно в 95% случаев. Семантика типа значения в конечном итоге кусает вас в заднице чаще, чем не в дороге.

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

Ответ 5

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

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

Ответ 6

Одно эмпирическое правило, на которое вы можете следовать, - спросить себя о том, нравится ли вам то, что вы пытаетесь сделать, например: System.Date. Если это не так, тогда вам действительно нужно поставить под сомнение свое решение использовать структуры.

Ответ 7

struct - это тип значения, а класс - ссылочный. это может быть одной из причин.

Ответ 8

Для простых типов, в которых у вас будет много из них, не требуется наследование, и они являются хорошим кандидатом на неизменность, а структуры - хороший выбор. Примерами этого являются Point, Rectangle, Decimal и DateTime.

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

Ответ 9

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

Если что-то велико, тогда класс:)

Ответ 10

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

Ответ 11

Нет необходимости выделять/освобождать структуры.