【问题标题】: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 并引发相应的错误。

      【讨论】:

        【解决方案3】:

        从 F# 4.1 开始,有 struct discriminated unions

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

        它们具有区分联合的优越匹配。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-06-01
          • 2021-09-26
          相关资源
          最近更新 更多