枚举与非成员歧视工会
只有一点点区别
type Color =
| Red
| Green
| Blue
我刚刚注意到声明非成员歧视联合体和声明枚举
type Color =
| Red = 0
| Green = 1
| Blue = 2
:它们在性能、用法等方面的主要区别是什么?您有什么建议何时使用什么?
I've just noticed that there's only a little difference in declaring a non-member discriminated union:
type Color =
| Red
| Green
| Blue
and declaring an enum:
type Color =
| Red = 0
| Green = 1
| Blue = 2
What are their main differences in terms of performance, usage, etc? Do you have suggestions when to use what?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
枚举是结构,因此在堆栈上分配,而可区分联合是引用类型,因此在堆上分配。因此,您可能会期望 DU 的性能略低于枚举,尽管实际上您可能永远不会注意到这种差异。
更重要的是,可区分联合只能是声明的类型之一,因为枚举实际上只是一个整数,因此您可以将不是枚举成员的整数转换为枚举类型。这意味着,当模式匹配时,当您覆盖了 DU 的所有情况时,编译器可以断言模式匹配已完成,但对于枚举,您必须始终放入默认捕获所有其余情况,即对于枚举,您总是需要模式匹配,例如:
最后一种情况对于 DU 来说是不必要的。
最后一点,由于 C# 和 VB.NET 都原生支持枚举,而 DU 则不然,因此在创建供其他语言使用的公共 API 时,枚举通常是更好的选择。
Enum are stucts and are therefore allocated on the stack, while discriminated unions are references types so are heap allocated. So, you would expect DU to be slightly less performant that enums, though in reality you'll probably never notice this difference.
More importantly a discriminated union can only ever be one of the types declared, where as enums are really just an integer, so you could cast an integer that isn't a member of the enum to the enum type. This means that when pattern matching the compiler can assert that the pattern matching is complete when you've covered all the cases for a DU, but for an enum you must always put in a default catch all the rest case, i.e for an enum you'll always need pattern matching like:
where as the last case would not be necessary with an DU.
One final point, as enums are natively supported in both C# and VB.NET, were as DUs are not, enums are often a better choice when creating a public API for consumption by other languages.
除了罗伯特所说的之外,联合上的模式匹配是通过两种方式之一完成的。对于仅具有空值情况的联合,即没有关联值的情况(这与枚举密切相关),将检查编译器生成的
Tag
属性,该属性是一个int
。在这种情况下,您可以预期性能与枚举相同。对于具有非空情况的联合,使用类型测试,我认为这也相当快。正如罗伯特所说,如果存在性能差异,则可以忽略不计。但在前一种情况下,它应该完全相同。关于枚举固有的“不完整性”,当模式匹配失败时,您真正想知道的是匹配是否未涵盖有效的情况。您通常不关心是否将无效的整数值转换为枚举。在这种情况下,您希望比赛失败。我几乎总是更喜欢联合,但是当我必须使用枚举(通常是为了互操作性)时,在强制通配符的情况下,我将不匹配的值传递给 区分有效值和无效值并引发适当错误的函数。
In addition to what Robert has said, pattern matching on unions is done in one of two ways. For unions with only nullary cases, i.e., cases without an associated value (this corresponds closely to enums), the compiler-generated
Tag
property is checked, which is anint
. In this case you can expect performance to be the same as with enums. For unions having non-nullary cases, a type test is used, which I assume is also pretty fast. As Robert said, if there is a performance discrepancy it's negligible. But in the former case it should be exactly the same.Regarding the inherent "incompleteness" of enums, when a pattern match fails what you really want to know is if a valid case wasn't covered by the match. You don't generally care if an invalid integer value was casted to the enum. In that case you want the match to fail. I almost always prefer unions, but when I have to use enums (usually for interoperability), inside the obligatory wildcard case I pass the unmatched value to a function that distinguishes between valid and invalid values and raises the appropriate error.
从 F# 4.1 开始,有 构造有区别的联合。
它们具有堆栈分配的性能优势,例如枚举。
他们拥有受歧视工会的优越匹配。
它们是 F# 特定的,因此如果您需要被其他 .Net 语言理解,您仍然应该使用枚举。
As of F# 4.1 there are struct discriminated unions.
These have the performance benefits of stack allocation, like enums.
They have the superior matching of discriminated unions.
They are F# specific so if you need to be understood by other .Net languages you should still use enums.