簡體   English   中英

如何枚舉 F# 中的枚舉/類型

[英]How to enumerate an enum/type in F#

我有一個像這樣定義的枚舉類型:

type tags = 
    | ART  = 0
    | N    = 1
    | V    = 2 
    | P    = 3
    | NULL = 4

有沒有辦法做一個for... in tags do呢?

這是我得到的錯誤:

未定義值、構造函數、命名空間或類型tags

使用Enum.GetValues

let allTags = Enum.GetValues(typeof<tags>)

這是一個完整的示例,打印有關任何歧視聯合的信息。 它顯示了如何獲得歧視聯合的案例以及如何獲取字段(如果您需要它們)。 該函數打印給定的區分聯合的類型聲明:

open System
open Microsoft.FSharp.Reflection

let printUnionInfo (typ:Type) = 
  printfn "type %s =" typ.Name
  // For all discriminated union cases
  for case in FSharpType.GetUnionCases(typ) do
    printf "  | %s" case.Name
    let flds = case.GetFields()
    // If there are any fields, print field infos
    if flds.Length > 0 then 
      // Concatenate names of types of the fields
      let args = String.concat " * " [ for fld in flds -> fld.PropertyType.Name ] 
      printf " of %s" args
    printfn ""    

// Example
printUnionInfo(typeof<option<int>>)

怎么樣:

let enumToList<'a> = (Enum.GetValues(typeof<'a>) :?> ('a [])) |> Array.toList

這具有提供強類型列表的優點

要使用只做:

let tagList = enumToList<tags>

要使它成為枚舉,您需要為每個案例顯式賦值,否則它是一個聯合類型:

type tags = 
    | ART = 0
    | N = 1
    | V = 2
    | P = 3
    | NULL= 4
let allTags = System.Enum.GetValues(typeof<tags>)

您可以使用Enum.GetValues ,它返回一個對象Array ,然后您必須將其向下轉換為整數值。 (注意:我正在使用Mono的F#實現;也許與.NET有所不同。)

以下是我編寫的一些函數,用於獲取所有枚舉值的列表並獲取最小值和最大值:

open System

module EnumUtil =

    /// Return all values for an enumeration type
    let EnumValues (enumType : Type) : int list =
        let values = Enum.GetValues enumType
        let lb = values.GetLowerBound 0
        let ub = values.GetUpperBound 0
        [lb .. ub] |> List.map (fun i -> values.GetValue i :?> int) 

    /// Return minimum and maximum values for an enumeration type
    let EnumValueRange (enumType : Type) : int * int =
        let values = EnumValues enumType
        (List.min values), (List.max values)

羅伯特關於如何生成實際枚舉並得到其案例的權利。 如果您具有真正的聯合類型,則可以通過Microsoft.FSharp.Reflection.FSharpType.GetUnionCases函數獲取案例。

在.Net 5 中有一個 Enum.GetValues 的通用重載,它消除了強制轉換的需要。

Enum.GetValues<T>()
type Options = 
    | Exit          = 0
    | CreateAccount = 1

Console.WriteLine()
Console.WriteLine("Choose an option:")
let allOptions = Enum.GetValues(typeof<Options>)
for option in allOptions do
    if (option <> null) then
        Console.WriteLine(sprintf "%d: %s" (option :?> int) (option.ToString()))
let optionChosen = System.Console.ReadLine()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM