Enum与非成员歧视联盟

时间:2012-02-03 08:36:01

标签: f# enums discriminated-union

我刚才注意到宣布非成员歧视联盟只有一点点差异:

type Color =
    | Red
    | Green
    | Blue

并声明一个枚举:

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

它们在性能,使用方面等方面的主要区别是什么?你有什么建议何时使用?

3 个答案:

答案 0 :(得分:14)

枚举是stucts,因此在堆栈上分配,而有区别的联合是引用类型,因此堆分配。所以,你会发现DU的枚举效果稍差,但实际上你可能从未注意到这种差异。

更重要的是,区分联合只能是声明的类型之一,因为枚举实际上只是一个整数,所以你可以将一个不是枚举成员的整数转换为枚举类型。这意味着当模式匹配时,编译器可以断言模式匹配完成时,你已经覆盖了DU的所有情况,但对于枚举,你必须总是在默认情况下捕获所有其他情况,即对于枚举你总是需要模式匹配,如:

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

如果最后一个案例不需要DU。

最后一点,因为在C#和VB.NET中本地支持枚举,因为DU不是,在创建供其他语言使用的公共API时,枚举通常是更好的选择。

答案 1 :(得分:6)

除了Robert所说的,工会上的模式​​匹配是以两种方式之一完成的。对于仅具有nullary情况的联合,即没有关联值的情况(这与枚举紧密对应),将检查编译器生成的Tag属性,即int。在这种情况下,您可以期望性能与枚举相同。对于具有非nullary情况的工会,使用类型测试,我认为这也非常快。正如罗伯特所说,如果性能差异可以忽略不计。但在前一种情况下它应该完全相同。

关于枚举的固有“不完整性”,当模式匹配失败时,您真正想知道的是匹配是否包含有效案例。您通常不关心是否将无效的整数值转换为枚举。在这种情况下,您希望匹配失败。我几乎总是喜欢工会,但是当我必须使用枚举(通常用于互操作性)时,在强制性通配符的情况下,我将不匹配的值传递给a function that distinguishes between valid and invalid values并引发相应的错误。

答案 2 :(得分:0)

从F#4.1开始,有struct discriminated unions

这些具有堆栈分配的性能优势,如枚举。

他们与受歧视的工会有着优越的匹配。

它们是F#特定的,因此如果您需要被其他.Net语言理解,您仍应使用枚举。

相关问题