Was ist der Enum.GetName Äquivalent für F # union-Mitglied?
-
12-09-2019 - |
Frage
Ich möchte das Äquivalent von Enum.GetName
für ein F # diskriminiert Gewerkschaftsmitglied bekommen. ToString()
Aufruf gibt mir Type-Namen + Member, die nicht genau das, was ich will. Ich kann es String, natürlich, aber ist es sicher? Oder vielleicht gibt es einen besseren Weg?
Lösung
Sie müssen die Klassen im Microsoft.FSharp.Reflection
Namespace verwenden, so:
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"|]
Andere Tipps
@ DanielAsher Antwort funktioniert, aber es eleganter zu machen, würde ich es auf diese Weise tun (und schnell, weil der Mangel an Reflexion für eine der Methoden?):
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
(inspiriert von diese und
Ich möchte etwas noch prägnante vorzuschlagen: Wenn Vereinigung Fall einfach ist, Wenn jedoch Vereinigung Fall ist schicker, wird es einen Unterschied :. 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()
die gleiche wie ToString()
bringen kann: > 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;}"