【发布时间】:2010-02-02 04:48:09
【问题描述】:
我有一个这样定义的枚举类型:
type tags =
| ART = 0
| N = 1
| V = 2
| P = 3
| NULL = 4
有没有办法做一个for ... in tags do?
这是我得到的错误:
值、构造函数、命名空间或 类型
tags未定义
【问题讨论】:
-
这不是枚举,而是联合。
我有一个这样定义的枚举类型:
type tags =
| ART = 0
| N = 1
| V = 2
| P = 3
| NULL = 4
有没有办法做一个for ... in tags do?
这是我得到的错误:
值、构造函数、命名空间或 类型
tags未定义
【问题讨论】:
怎么样:
let enumToList<'a> = (Enum.GetValues(typeof<'a>) :?> ('a [])) |> Array.toList
这具有提供强类型列表的优点
使用只是做:
let tagList = enumToList<tags>
【讨论】:
int 值。
let allTags = Enum.GetValues(typeof<tags>)
【讨论】:
enum<tags> tag,但没用。
这是一个完整的示例,它打印有关任何受歧视联合的信息。它显示了如何获取受歧视联合的案例以及如何获取字段(如果您需要它们)。该函数打印给定可区分联合的类型声明:
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>>)
【讨论】:
tags 定义为枚举时引入了混淆。
要使其成为枚举,您需要为每种情况显式赋予值,否则它是联合类型:
type tags =
| ART = 0
| N = 1
| V = 2
| P = 3
| NULL= 4
let allTags = System.Enum.GetValues(typeof<tags>)
【讨论】:
罗伯特关于如何生成一个实际的枚举并获取它的案例是正确的。如果你有真正的联合类型,你可以通过Microsoft.FSharp.Reflection.FSharpType.GetUnionCases 函数获取案例。
【讨论】:
您可以使用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)
【讨论】:
在 .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()
【讨论】: