Выбор между классами и структурами - PullRequest
6 голосов
/ 30 июля 2011

Статья MSDN на C # с именем Выбор между классами и структурами дает следующий совет:

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

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

It logically represents a single value, similar to primitive types

(целое, двойное и т. Д.).

It has an instance size smaller than 16 bytes.

It is immutable.

It will not have to be boxed frequently. 

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

Интересно, каким будет ответ в случае D. До сих пор я просто использовал структуры во всех случаях, когда мне не нужен полиморфизм. Я не знаю, является ли размер также фактором. Или что-нибудь еще.

Ответы [ 4 ]

8 голосов
/ 30 июля 2011

В D есть несколько ключевых отличий от C #, которые делают идиоматичным использование struct чаще:

  1. Нет автобокса, потому что проблемы, которые он решает, обычно решаются с помощьюшаблоны.

  2. В настоящее время сборщик мусора менее эффективен.

  3. Указатели на структуры работают в большинстве случаев хорошо, если вам нужна ссылочная семантика.(Единственное серьезное исключение состоит в том, что указатели на структуры с перегруженными арифметическими или индексными операторами ведут себя странно, потому что операции обрабатываются как арифметика указателей, а не вызывают перегрузки операторов.) Кроме того, структуры могут легко распределяться в куче с помощью оператора new.

  4. Структуры могут иметь детерминированные деструкторы (не финализаторы), конструкторы копирования и т. Д., Поэтому вы можете использовать магию с ними, как в C ++.

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

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

7 голосов
/ 31 июля 2011

Я бы сказал, что этот совет определенно не применим к D.

Структуры являются типами значений.Классы являются ссылочными типами.Структуры обычно находятся в стеке (хотя они могут быть в куче и указываться указателями).Занятия в куче.Структуры не имеют наследования или полиморфизма.Классы имеют наследование и полиморфизм.

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

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

И, наконец, если тип содержит много данных и вам не нужно иметькопируйте его всякий раз, когда вы передаете его в функцию, тогда было бы более эффективно сделать его классом и копировать его только тогда, когда вам это действительно нужно (хотя вы можете выбрать просто всегда передавать его вместо ref вместо).

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

Мне кажется, что рекомендации по C # проистекают из двух вопросов:

  1. Тот факт, что структуры являютсятипы значений и, следовательно, имеют семантику значений.
  2. Тот факт, что структуры в C # имеют дело с автобоксом и должен очень беспокоиться о стоимости копирования.

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

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

Итак, нет, я не думаю, что совет C # действительно применим к D.Ситуация между двумя языками просто слишком различна.Было бы лучше думать о структурах D как о классах C ++, которые не имеют каких-либо базовых классов и не могут быть получены из них, поскольку это гораздо ближе к тому, чем они на самом деле являются, чем структуры C #.

1 голос
/ 30 июля 2011

структуры передаются по значению, поэтому размер действительно учитывается (хотя этого можно избежать при ref и in)

в основном вы должны использовать структуры, когда вам нужно передать только по значению (изменения объекта не должны распространяться) или это недолговечный объект, срок жизни которого достаточно короткий, чтобы оставаться в стеке (например, объект диапазона, как вы) Посмотрим в модуле std.algorithm; все функции там почти все возвращают структуру)

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

0 голосов
/ 30 июля 2011

В отношении D обычно применяются те же рекомендации, что и в C #, - они в значительной степени совпадают.

Единственное исключение - рекомендация boxing - она ​​не применяется, поскольку в D. на самом деле бокс не существует изначально.

...