Я хочу получить эквивалент Enum.GetName
для члена с ограниченным членством F #. Вызов ToString()
дает мне TypeName + MemberName, что не совсем то, что я хочу. Я мог бы подстроить его, конечно, но это безопасно? Или, может быть, есть лучший способ?
Что такое эквивалент Enum.GetName для члена объединения F #?
Ответ 1
Вам нужно использовать классы в пространстве имен 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
@Ответ 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
Ответ 3
Я хотел бы предложить что-то более сжатое:
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;}"