2009-08-11 69 views
16

我想要得到相当于Enum.GetName的F#区分联盟成员。调用ToString()给了我TypeName + MemberName,这不完全是我想要的。当然,我可以将其子串,但它是否安全?或者也许有更好的方法?什么是F#联合成员的Enum.GetName等价物?

+1

当心!非常相同的表达式x.ToString()将在不同的程序运行时有时会给我AssemblyName + TypeName,有时还会给我AssemblyName + TypeName + MemberName。在其他地方的另一个相同的表达式总是会给我AssemblyName + TypeName + MemberName。与x.GetType()。名称相同的问题。接受的答案是好的。 – 2016-05-23 08:28:04

回答

26

您需要使用的类在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"|] 
+1

我来到这里是为了获取'''GetUnionFields'''语法 - 谢谢你。 虽然我在这里,但我想我会指出'GetUnionCaseName''可以写得稍微简洁一点: ''让GetUnionCaseName(e:'a)=(FSharpValue.GetUnionFields(e,typeof <'a>)|> fst).Name''' – philsquared 2015-01-26 17:35:41

+0

请注意,这是一个非常缓慢的方法,您一定想要缓存结果以便获得一些性能。 – 2016-01-28 15:23:37

2

@ DanielAsher的回答作品,而是使之更优雅,我会做这种方式:(通过thisthis启发)

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

我想提出一些更简洁:

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;}" 
相关问题