Во-первых, это не Отчеты - это Дискриминационные Союзы. Запись - это простая совокупность именованных данных с сгенерированным равенством / хэшированием, и создание из нее структуры также возможно, но не сопряжено с дополнительными требованиями.
Более строгие требования для структуры Дискриминационные объединения:
- Нет вызываемого конструктора по умолчанию
- Нет циклов c ссылки / нет рекурсивных определений
- У нескольких случаев должны быть уникальные имена
Первые два точки присуще тому, чтобы быть типами значения. Значения и ссылочные типы просто разные.
Последний пункт интересен. Рассмотрим следующее:
type DU1 =
| Case1 of string
| Case2 of float
[<Struct>]
type DU2 =
| Case1 of sval: string
| Case2 of fval: float
В случае DU1
существует внутренний класс для каждого случая, и они содержат свойства для доступа к базовым данным. Эти свойства называются Item1
, Item2
и т. Д., И поскольку они инкапсулированы во внутреннем классе, при обращении к ним они уникальны.
В случае DU2
, sval
и fval
значения выложены ровно; нет внутреннего класса, который их содержит. Это потому, что целью является производительность / размер структуры. Стратегия именования данных в объединенном случае (Item1
/ Item2
/ et c.) Не применяется, потому что все данные выложены ровно. И поэтому дизайнерское решение состояло в том, чтобы потребовать уникальных именованных случаев, а не применять некоторые хитрости для объединения имени самого случая и некоторого изменения Item1
/ Item2
/ et c. Проблема уникальности присуща дизайну самих союзов в компиляторе, а не просто выбору дизайна codegen.
Наконец, на этот вопрос есть еще один интересный ответ:
Почему нет F # по умолчанию для структур для записей?
Кортежи, записи и DU в F # могут быть помечены как [<Struct>]
, но не являются структурами по умолчанию. Это потому, что структуры - это не просто кнопка «сделать ее более эффективной», которую вы можете использовать. Часто производительность процессора снижается из-за чрезмерного копирования, поскольку ваши структуры слишком велики. В F # вполне нормально иметь большие кортежи и очень очень большие записи и различающиеся объединения. Создание этих структур по умолчанию не будет хорошим выбором. Ссылочные типы очень мощные и рассчитаны на очень хорошую работу. NET, и их не следует избегать по умолчанию только потому, что в некоторых случаях структура может привести к несколько большей производительности.
Когда вы беспокоитесь о производительности, никогда не меняйте вещи только на основании предположений или интуиции: используйте инструменты профилирования, такие как PerfView, dotTrace или dotMemory; и оцените небольшие изменения с помощью статистических инструментов, таких как BenchmarkDo tNet. Производительность является чрезвычайно сложным пространством и редко становится чем-то простым, когда вы закончите с учетом вопиющих проблем, которые явно плохие (например, алгоритмы O (n ^ 2) для больших наборов данных или что-то в этом роде).