«Накладные расходы» класса против структуры в C #? - PullRequest
14 голосов
/ 04 мая 2010

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

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

Ответы [ 11 ]

12 голосов
/ 04 мая 2010

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

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

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

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

9 голосов
/ 04 мая 2010

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

MSDN имеет страницу на , выбирая классы и структуры .

Резюме:

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

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

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

8 голосов
/ 04 мая 2010

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

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

2 голосов
/ 04 мая 2010

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

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

1 голос
/ 04 мая 2010

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

1 голос
/ 04 мая 2010

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

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

0 голосов
/ 04 мая 2010

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

0 голосов
/ 04 мая 2010

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

Если что-то большое, то класс :))

0 голосов
/ 04 мая 2010

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

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

0 голосов
/ 04 мая 2010

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

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