Enum против беспристрастного дискриминационного союза

Я только что заметил, что только небольшое различие в объявлении не членского дискриминационного союза:

type Color =
    | Red
    | Green
    | Blue

и объявление перечисления:

type Color =
    | Red = 0 
    | Green = 1
    | Blue = 2

В чем их основные отличия в плане производительности, использования и т.д.? У вас есть предложения по использованию чего?

Ответы

Ответ 1

Enum являются столбцами и поэтому распределяются в стеке, в то время как дискриминационные объединения являются типами ссылок, поэтому выделены кучи. Таким образом, вы ожидаете, что DU будет немного менее результативным, чем перечисление, хотя на самом деле вы, вероятно, никогда не заметите эту разницу.

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

match enumColor with
| Red -> 1 
| Green -> 2
| Blue -> 3
| _ -> failwith "not an enum member"

где, поскольку последний случай не был бы необходим с DU.

Одна конечная точка, поскольку перечисления поддерживаются как в С#, так и в VB.NET, были такими же, как и DU, перечисления часто являются лучшим выбором при создании публичного API для потребления другими языками.

Ответ 2

В дополнение к тому, что сказал Роберт, сопоставление образцов в союзах осуществляется одним из двух способов. Для объединений с только нулевыми случаями, то есть случаев без привязанного значения (это близко соответствует перечислениям), проверяется свойство Tag, генерируемое компилятором, которое является int. В этом случае вы можете ожидать, что производительность будет такой же, как и с перечислениями. Для профсоюзов, имеющих непустые случаи, используется тест типа, который, как я полагаю, также довольно быстро. Как сказал Роберт, если есть расхождение в производительности, это незначительно. Но в первом случае он должен быть точно таким же.

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

Ответ 3

Начиная с F # 4.1 существуют структурированные объединения.

У них есть преимущества производительности распределения стека, например перечисления.

У них есть превосходное совпадение дискриминационных союзов.

Они специфичны для F #, поэтому, если вам нужно понимать другие языки .Net, вы все равно должны использовать перечисления.