Когда использовать структуру? - PullRequest
1307 голосов
/ 06 февраля 2009

Когда вы должны использовать структуру, а не класс в C #? Моя концептуальная модель состоит в том, что структуры используются во времена, когда элемент является просто набором значений . Способ логически объединить их все в единое целое.

Я сталкивался с этими правилами здесь :

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

Эти правила работают? Что означает семантически структура?

Ответы [ 28 ]

4 голосов
/ 24 октября 2017

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

Итак, вы должны использовать структуры, когда вы хотите представить более простые структуры данных, особенно если вы знаете, что будете создавать их экземпляры. Существует множество примеров в .NET Framework, где Microsoft использует структуры вместо классов, например структуру Point, Rectangle и Color.

4 голосов
/ 06 февраля 2009

Я думаю, что хорошее первое приближение - "никогда".

Я думаю, что хорошее второе приближение - "никогда".

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

3 голосов
/ 26 мая 2016

Вкратце, используйте struct, если:

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

2- свойства и поля в вашем объекте являются типом значения, и они не так велики.

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

3 голосов
/ 31 августа 2015

Типы структуры или значения могут использоваться в следующих сценариях -

  1. Если вы хотите предотвратить сбор объекта при сборке мусора.
  2. Если это простой тип и никакая функция-член не изменяет свои поля экземпляра
  3. Если нет необходимости выводить из других типов или выводить из других типов.

Вы можете узнать больше о типах значений и значениях типов здесь по этой ссылке

3 голосов
/ 03 июля 2013

Struct можно использовать для повышения производительности сборки мусора. Хотя вам обычно не нужно беспокоиться о производительности GC, есть сценарии, где это может быть убийственно. Как большие кэши в приложениях с низкой задержкой. Смотрите этот пост для примера:

http://00sharp.wordpress.com/2013/07/03/a-case-for-the-struct/

2 голосов
/ 06 февраля 2009

Я редко использую структуру для вещей. Но это только я. Это зависит от того, нужен ли мне объект или нет.

Как указано в других ответах, я использую классы для объектов реального мира. У меня также есть мышление структур, которые используются для хранения небольших объемов данных.

1 голос
/ 27 февраля 2019

МИФ № 1: СТРУКТЫ - ЛЕГКИЕ КЛАССЫ

Этот миф имеет множество форм. Некоторые люди считают, что типы значений не могут или не должно иметь методов или другого значимого поведения - их следует использовать как простые типы передачи данных, только с открытыми полями или простыми свойствами. Тип DateTime является хороший контрпример к этому: имеет смысл для него быть типом значения, с точки зрения фундаментальная единица, такая как число или символ, и также имеет смысл для него быть способен выполнять расчеты на основе его стоимости. Глядя на вещи с другой направление, типы передачи данных часто должны быть ссылочными типами в любом случае - решение должны основываться на желаемом значении или семантике ссылочного типа, а не на простоте тип. Другие люди считают, что типы значений «легче», чем ссылочные типы в терминах производительности. Правда в том, что в некоторых случаях типы значений более производительны - им не требуется сборка мусора, если они не упакованы, не имеют тип накладные расходы на идентификацию и не требуют разыменования, например. Но в других пути, ссылочные типы более производительны - передача параметров, присвоение значений Переменные, возвращаемые значения и подобные операции требуют только 4 или 8 байтов для копирования (в зависимости от того, используете ли вы 32-разрядную или 64-разрядную версию CLR), а не копирование всех данных. Представьте, что ArrayList был каким-то «чистым» типом значения, и Передача выражения ArrayList методу, включающему копирование всех его данных! Почти во всех случаях производительность не зависит от такого рода решений. Узкие места почти никогда не бывают такими, какими вы их считаете, и прежде чем принимать проектное решение, основанное на производительности, вы должны измерить различные варианты. Стоит отметить, что сочетание двух убеждений тоже не работает. Это не имеет значения, сколько методов имеет тип (будь то класс или структура) - память, взятая за экземпляр, не затрагивается. (Там есть стоимость с точки зрения памяти взят за сам код, но это происходит один раз, а не для каждого экземпляра.)

МИФ № 2: СПРАВОЧНЫЕ ТИПЫ ЖИВАЯ НА КРУГЕ; ЦЕННЫЕ ТИПЫ ЖИТЬ НА СТЕКЕ

Это часто вызывается ленью повторяющего его человека. Первый часть верна - экземпляр ссылочного типа всегда создается в куче. Это Вторая часть, которая вызывает проблемы. Как я уже отмечал, значение переменной живет везде, где она объявлена, поэтому, если у вас есть класс с переменной экземпляра типа int, значение этой переменной для любого данного объекта всегда будет там, где остальные данные для объекта это в куче. Только локальные переменные (переменные, объявленные в методах) и метод параметры живут в стеке. В C # 2 и более поздних версиях даже некоторые локальные переменные жить в стеке, как вы увидите, когда мы рассмотрим анонимные методы в главе 5. СООТВЕТСТВУЮТ ЛИ ЭТИ КОНЦЕПЦИИ СЕЙЧАС? Можно утверждать, что если вы пишете управляемый код, вы должны позволить среде выполнения беспокоиться о том, как лучше всего использовать память. Действительно, спецификация языка не дает никаких гарантий о том, что живет где; будущая среда выполнения может создать несколько объектов в стеке, если знает, что это может сойти с рук, или компилятор C # может генерировать код, который вряд ли использует стек вообще. Следующий миф обычно является просто вопросом терминологии.

МИФ № 3: ОБЪЕКТЫ ПРОЙДЕНЫ ПО ССЫЛКЕ В C # ПО УМОЛЧАНИЮ

Это, наверное, самый распространенный миф. Опять же, люди, которые делают это утверждают, часто (хотя и не всегда) знают, как на самом деле ведет себя C #, но они не знают что на самом деле означает «передать по ссылке». К сожалению, это сбивает с толку людей, которые знаю, что это значит. Формальное определение передачи по ссылке относительно сложное, включающее l-значения и подобная компьютерная терминология, но важно то, что если вы передадите переменная по ссылке, метод, который вы вызываете, может изменить значение cпеременная аллерга путем изменения значения его параметра. Теперь помните, что значение ссылки Переменная типа - это ссылка, а не сам объект. Вы можете изменить содержимое объект, на который ссылается параметр без передачи самого параметра по ссылке. Например, следующий метод изменяет содержимое StringBuilder объект, о котором идет речь, но выражение вызывающего все равно будет ссылаться на тот же объект, что и раньше:

void AppendHello(StringBuilder builder)
{
    builder.Append("hello");
}

Когда этот метод вызывается, значение параметра (ссылка на StringBuilder) передается по значению. Если бы вы изменили значение переменной построителя в метод - например, с помощью оператора builder = null; - это изменение не будет видел вызывающий, вопреки мифу. Интересно отметить, что не только бит «по ссылке» мифа неточен, но и бит «объекты переданы». Сами объекты никогда не передаются, либо по ссылке или по значению. Когда задействован ссылочный тип, либо переменная передается по ссылке или значение аргумента (ссылка) передается по значению. Помимо всего прочего, это отвечает на вопрос, что происходит, когда ноль используется в качестве аргумента по значению - если объекты передаются, это приведет к проблемы, так как не было бы объекта для передачи! Вместо этого нулевая ссылка передается значение так же, как и любая другая ссылка. Если это быстрое объяснение оставило вас в замешательстве, вы можете посмотреть мою статью «Передача параметров в C #» (http://mng.bz/otVt),, которая затрагивает гораздо больше подробно. Эти мифы не единственные вокруг. Бокс и распаковка приходят за своими справедливая доля недоразумений, которые я постараюсь прояснить в следующем.

Справка: C # в 3-м издании по глубине от Jon Skeet

0 голосов
/ 20 ноября 2014

Структуры в большинстве своем похожи на классы / объекты. Структура может содержать функции, члены и может быть унаследована. Но структуры в C # используются только для данных, содержащих . Структуры занимают меньше ОЗУ , чем классы, и сборщику мусора легче . Но когда вы используете функции в своей структуре, то компилятор фактически принимает эту структуру очень похоже на класс / объект, поэтому, если вам нужно что-то с функциями, используйте класс / объект .

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