¿Cuál es el equivalente Enum.GetName para el miembro de la unión F#?
enum to list c# (3)
Quiero obtener el equivalente de Enum.GetName
para un miembro de la unión discriminado por F #. Llamar a ToString()
me da TypeName + MemberName, que no es exactamente lo que quiero. Podría subscribirlo, por supuesto, pero ¿es seguro? O tal vez hay una mejor manera?
Debe usar las clases en el espacio de nombres Microsoft.FSharp.Reflection
para:
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"|]
La respuesta de @ DanielAsher funciona, pero para hacerlo más elegante (¿y rápido? Debido a la falta de reflexión de uno de los métodos), lo haría de esta manera:
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
(Inspirado por this y this .)
Me gustaría proponer algo aún más conciso:
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
Cuando Union GetName()
es simple, GetName()
puede traer lo mismo que ToString()
:
> let tea = Tea
val tea : Beverage = Tea
> tea.GetName()
val it : string = "Tea"
> tea.ToString()
val it : string = "Tea"
Sin embargo, si el caso de la unión es más elegante, habrá una diferencia:
> 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;}"