【问题标题】:Enum vs non-member discriminated union枚举与非成员歧视工会
【发布时间】:2012-02-25 21:38:16
【问题描述】:
我刚刚注意到声明非成员歧视工会只有一点区别:
type Color =
| Red
| Green
| Blue
并声明一个枚举:
type Color =
| Red = 0
| Green = 1
| Blue = 2
它们在性能、使用等方面的主要区别是什么?你有什么建议什么时候用什么?
【问题讨论】:
标签:
f#
enums
discriminated-union
【解决方案1】:
枚举是结构,因此分配在堆栈上,而区分联合是引用类型,因此是堆分配的。因此,您会认为 DU 的性能比枚举稍差,但实际上您可能永远不会注意到这种差异。
更重要的是,可区分联合只能是声明的类型之一,因为枚举实际上只是一个整数,因此您可以将一个不是枚举成员的整数强制转换为枚举类型。这意味着当模式匹配时,编译器可以断言模式匹配已完成,当您涵盖了 DU 的所有情况时,但是对于枚举,您必须始终放入默认捕获所有其余情况,即对于您的枚举'总是需要像这样的模式匹配:
match enumColor with
| Red -> 1
| Green -> 2
| Blue -> 3
| _ -> failwith "not an enum member"
最后一种情况对于 DU 来说是不必要的。
最后一点,由于 C# 和 VB.NET 都原生支持枚举,而 DU 不支持,因此在创建公共 API 以供其他语言使用时,枚举通常是更好的选择。
【解决方案2】:
除了 Robert 所说的之外,联合上的模式匹配是通过以下两种方式之一完成的。对于只有空值情况的联合,即没有关联值的情况(这与枚举密切对应),检查编译器生成的Tag 属性,即int。在这种情况下,您可以期望性能与枚举相同。对于具有非空案例的联合,使用类型测试,我认为这也很快。正如罗伯特所说,如果存在性能差异,则可以忽略不计。但是前一种情况应该是完全一样的。
关于枚举固有的“不完整性”,当模式匹配失败时,您真正想知道的是匹配是否未涵盖有效案例。您通常不关心是否将无效的整数值强制转换为枚举。在这种情况下,您希望匹配失败。我几乎总是更喜欢联合,但是当我必须使用枚举(通常是为了互操作性)时,在强制通配符的情况下,我将不匹配的值传递给 a function that distinguishes between valid and invalid values 并引发相应的错误。