2016-03-01 12 views
9

Esaminiamo la seguente parte di codice e presupponiamo che non sia possibile modificare la funzione MyAttribute e test.Come conservare il tipo di valore in enum

type MyAttribute() = 
    inherit Attribute() 

    let mutable prop = null 

    member this.Prop 
     with get(): obj = prop 
     and set(value) = prop <- value 


type MyEnum = 
    | A = 1 
    | B = 2 

[<My(Prop = MyEnum.B)>] 
type MyClass = class 
    end 

let test() = 
    let t = typeof<MyClass> 
    let a = t.GetCustomAttributes(false).[0] :?> MyAttribute 

    let e = a.Prop 
    Convert.ToString(e, Globalization.CultureInfo.CurrentCulture) 

Mi aspetterei che test ritorno B ma restituisce 2. codice IL Generated mostra che le informazioni sul tipo enum è perso e valore passato da attribuire è solo 2.

C'è un modo (immagino dovrebbe essere un attributo) per preservare il tipo nel valore dell'attributo? Che cosa è codice equivalente più interessante in C# funziona come previsto

equivalente C#:

class MyAttribute : Attribute 
{ 
    public object A { get; set; } 
} 

enum T { A,B,C } 

[My(A = T.A)] 
class MyClass 
{ } 

var a = typeof(MyClass).GetCustomAttributes(false)[0] as MyAttribute; 

Convert.ToString(a.A, System.Globalization.CultureInfo.CurrentCulture) 
+1

Puoi condividere il codice C# equivalente che hai menzionato? – MarcinJuraszek

+0

@MarcinJuraszek: modificato – Novakov

+0

Stai chiamando 'GetCustomAttributes()' con 'false' in F # e' true' in C#; non sono sicuro di quello che fa, ma è una differenza almeno. – TeaDrivenDev

risposta

1

Sto indovinando e la mia conoscenza sui meccanismi interni del compilatore sono in realtà tranquilla limitato, ma credo che questo è qualcosa a che fare con tipo di inferenza. C'è un'equivalenza tra int < -> Enum, e ho il sospetto che l'inferenza di tipo sta riducendo questo al tipo più basso possibile, in questo caso int. Puoi risolvere il problema procedendo nel modo seguente

open System 

type MyAttribute() = 
    inherit Attribute() 

    let mutable prop = null 

    member this.Prop 
     with get(): obj = prop 
     and set(value) = prop <- value 


type MyEnum = 
    | A = 1 
    | B = 2 

[<My(Prop = MyEnum.B)>] 
type MyClass = class 
    end 

let test() = 
    let t = typeof<MyClass> 
    let a = t.GetCustomAttributes(false).[0] :?> MyAttribute 

    let e = a.Prop :?> MyEnum //Note 
    Convert.ToString(e, Globalization.CultureInfo.CurrentCulture) 
+0

Il problema è che non posso cambiare il codice responsabile della lettura di quella proprietà - è in un'altra libreria che non ha conoscenza del mio enum – Novakov

Problemi correlati