Неизменный класс против неизменяемой структуры - PullRequest
10 голосов
/ 17 августа 2011

У меня есть класс, в котором жизнь стала изменчивой, но с тех пор я сделал ее неизменной. Должен ли я изменить его на struct? Какие соображения относятся к выбору одного над другим? Мой частный случай - класс типа Point (он представляет координату в пользовательской системе координат), который состоит из 4 int полей, плюс несколько свойств для доступа к одним и тем же данным по-разному. Я отмечаю, что String является классом и является неизменным, поэтому для этого должен быть некоторый вариант использования.

Ответы [ 7 ]

6 голосов
/ 17 августа 2011

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

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

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

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

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

4 голосов
/ 17 августа 2011

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

Я совсем не специалист по этому вопросу, но хотел поднять этот аспект.Кто-то с большим опытом, безусловно, должен вмешаться и расширить это.Кроме того, вот полезное обсуждение этого вопроса: Когда использовать struct?

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

2 голосов
/ 17 августа 2011

Если он маленький и неизменный, то предпочтительнее сделать его структурой. Особенно, если у вас будет много коллекций очков. Если у вас есть список из 1 миллиона точек, тогда для всех этих объектов будет много служебной информации, как с точки зрения времени GC, так и 16 байтов дополнительной служебной информации на экземпляр объекта.

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

1 голос
/ 17 августа 2011

Храните его как класс, если только он не достаточно мал, чтобы структура имела смысл. Это будет редко. Я думаю, что, в общем, случаи "структурированности" быстро уменьшаются. Если бы сильные семантики были заложены в начале языка (неизменяемость и особенности объекта-значения предметной области), я бы передумал. В качестве довольно нового примера рассмотрим System.Tuple <>. Тем не менее, я бы немного хеджировал, спрашивая, каков ваш объект (риторически говоря).

0 голосов
/ 22 сентября 2011

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

  void doSomethingWithIFoo(IFoo whatever);

и

  void doSomethingWithIFoo<T>(T whatever) where T:IFoo;

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

0 голосов
/ 17 августа 2011

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

0 голосов
/ 17 августа 2011

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

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

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