Что такое эквивалент Enum.GetName для члена объединения F #? - PullRequest
18 голосов
/ 11 августа 2009

Я хочу получить эквивалент Enum.GetName для дискриминированного члена профсоюза F #. Вызов ToString() дает мне TypeName + MemberName, что не совсем то, что я хочу. Я мог бы, конечно, подстегнуть это, но безопасно ли это? Или, может быть, есть лучший способ?

Ответы [ 3 ]

28 голосов
/ 11 августа 2009

Вам необходимо использовать классы в пространстве имен Microsoft.FSharp.Reflection так:

open Microsoft.FSharp.Reflection

///Returns the case name of the object with union type 'ty.
let GetUnionCaseName (x:'a) = 
    match FSharpValue.GetUnionFields(x, typeof<'a>) with
    | case, _ -> case.Name  

///Returns the case names of union type 'ty.
let GetUnionCaseNames <'ty> () = 
    FSharpType.GetUnionCases(typeof<'ty>) |> Array.map (fun info -> info.Name)

// Example
type Beverage =
    | Coffee
    | Tea

let t = Tea
> val t : Beverage = Tea

GetUnionCaseName(t)
> val it : string = "Tea"

GetUnionCaseNames<Beverage>()
> val it : string array = [|"Coffee"; "Tea"|]
2 голосов
/ 17 декабря 2016

@ Ответ DanielAsher работает, но чтобы сделать его более элегантным (и быстрым? Из-за отсутствия отражения одного из методов), я бы сделал это следующим образом:

type Beverage =
    | Coffee
    | Tea
    static member ToStrings() =
        Microsoft.FSharp.Reflection.FSharpType.GetUnionCases(typeof<Beverage>)
            |> Array.map (fun info -> info.Name)
    override self.ToString() =
        sprintf "%A" self

(Вдохновленный этим и этим .)

0 голосов
/ 05 сентября 2017

Я хотел бы предложить что-то еще более краткое:

open Microsoft.FSharp.Reflection

type Coffee = { Country: string; Intensity: int }

type Beverage =
    | Tea
    | Coffee of Coffee

    member x.GetName() = 
        match FSharpValue.GetUnionFields(x, x.GetType()) with
        | (case, _) -> case.Name  

Если случай объединения прост, GetName() может принести то же самое, что и ToString():

> let tea = Tea
val tea : Beverage = Tea

> tea.GetName()
val it : string = "Tea"

> tea.ToString()
val it : string = "Tea"

Однако, если дело о союзе будет более изящным, будет разница :.

> let coffee = Coffee ({ Country = "Kenya"; Intensity = 42 })
val coffee : Beverage = Coffee {Country = "Kenya"; Intensity = 42;}

> coffee.GetName()
val it : string = "Coffee"

> coffee.ToString()
val it : string = "Coffee {Country = "Kenya";        Intensity = 42;}"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...