【问题标题】:Is there a .NET construct like Java's enum.ordinal()?有没有像 Java 的 enum.ordinal() 这样的 .NET 结构?
【发布时间】:2019-02-08 14:43:06
【问题描述】:

如果我在 F# 中有以下枚举:

type Note =
    | C = 0
    | D = 2
    | E = 4
    | F = 5
    | G = 7
    | A = 9
    | B = 11

但在某些时候,我需要其中项目的序数,例如 Note.C = 1, Note.D = 2, 等。显然在其他语言中,foo.ordinal() 可以工作,但在这里有必要使用这样的函数:

let getNoteOrdinal = function
    |Note.C -> 1
    |Note.D -> 2
    |Note.E -> 3
    |Note.F -> 4
    //etc

这个功能是必要的还是有更好的功能?

【问题讨论】:

    标签: .net enums f#


    【解决方案1】:

    .NET 中的枚举只是整数类型之上的一层,在这种情况下,您的值是 int

    根据the docs,您可以进行简单的转换以获得该值,例如:

    let value = int Note.B
    

    在这种情况下,value11

    要查找序数,您可以使用一个内置函数,该函数按顺序为您提供所有值的数组,然后找到您所追求的值的索引。例如:

    let getNoteOrdinal (note: Note) =
        let values = Enum.GetValues(typeof<Note>)
        Array.IndexOf(values, note) + 1
    
    let value = getNoteOrdinal Note.E
    
    

    在这种情况下,value 将是 3

    您可以按照@ReedCopsey 的建议更进一步,并创建一个通用函数,该函数将为您提供 any 枚举值的序数:

    let getEnumOrdinal (e: 'a when 'a : enum<'b> and 'a : equality) =    
        let values = Enum.GetValues(e.GetType())
        Array.IndexOf(values, e) + 1
    

    【讨论】:

    • 请注意,这与 OP 所追求的数字不同,但总的来说,无论如何,我发现在大多数情况下这是一种更好的方法。
    • @ReedCopsey 啊,原来如此!教我正确阅读。我会离开这里,因为它可能有用。
    • 是的,我在问是否有一种内置的方式来获取 ordinal a la Java 等,而不是 value
    • @LSM07 我很确定。当出现此类问题时,使用 F# 的一个技巧是在 C# 中搜索类似的解决方案。刚刚完成,我能找到的唯一结果与此实现类似。
    • @LSM07 一般来说,.NET 建议您将序数视为实现细节,而不是作为逻辑基础的东西。使用它几乎令人不悦。这有什么用例?
    【解决方案2】:

    我建议不要在 F# 中使用枚举,除非它需要与另一种 .NET 语言进行互操作。您可以使用有区别的联合并将注释值存储在一个数组中(这是一个模块级别的值,在应用程序启动时评估一次)。然后你可以编写使用数组的函数。

    type Note = C | D | E | F | G | A | B
    
    let noteValues =
        [| C, 0
           D, 2
           E, 4
           F, 5
           G, 7
           A, 9
           B, 11 |]
    
    let getNoteValue note =
        noteValues |> Array.find (fun (n, _) -> note = n) |> snd
    
    let getNoteOrdinal note =
        noteValues |> Array.findIndex (fun (n, _) -> n = note) |> (+) 1
    

    示例用法:

    getNoteValue C // 0
    getNoteValue D // 2
    
    getNoteOrdinal C // 1
    getNoteOrdinal D // 2
    

    【讨论】:

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