简体   繁体   English

如何枚举 F# 中的枚举/类型

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

I've got an enumeration type defined like so:我有一个像这样定义的枚举类型:

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

is there a way to do a for... in tags do ?有没有办法做一个for... in tags do呢?

This is the error that I'm getting:这是我得到的错误:

The value, constructor, namespace or type tags is not defined未定义值、构造函数、命名空间或类型tags

使用Enum.GetValues

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

Here is a complete example that prints information about any discriminated union. 这是一个完整的示例,打印有关任何歧视联合的信息。 It shows how to get cases of the discriminated union and also how to get the fields (in case you needed them). 它显示了如何获得歧视联合的案例以及如何获取字段(如果您需要它们)。 The function prints type declaration of the given discriminated union: 该函数打印给定的区分联合的类型声明:

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>>)

How about: 怎么样:

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

This has the advantage of providing a strongly typed list 这具有提供强类型列表的优点

To use just do: 要使用只做:

let tagList = enumToList<tags>

To make it an enum you need to explicitly give values to each case, otherwise it's a union type: 要使它成为枚举,您需要为每个案例显式赋值,否则它是一个联合类型:

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

You can use Enum.GetValues , which returns an Array of objects that you then have to downcast to integer values. 您可以使用Enum.GetValues ,它返回一个对象Array ,然后您必须将其向下转换为整数值。 (Note: I'm using Mono's F# implementation; maybe things are different with .NET.) (注意:我正在使用Mono的F#实现;也许与.NET有所不同。)

Here are some functions I wrote to get a list of all enumeration values and to get the min and max values: 以下是我编写的一些函数,用于获取所有枚举值的列表并获取最小值和最大值:

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)

Robert's right about how to generate an actual enum and get its cases. 罗伯特关于如何生成实际枚举并得到其案例的权利。 If you have a true union type, you can get the cases via the Microsoft.FSharp.Reflection.FSharpType.GetUnionCases function. 如果您具有真正的联合类型,则可以通过Microsoft.FSharp.Reflection.FSharpType.GetUnionCases函数获取案例。

In.Net 5 there is a generic overload of Enum.GetValues which eliminates the need for casting.在.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