Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to preserve value type in enum

Let's look at the following piece of code and assume that both MyAttribute and test function cannot be changed.

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)

I would expect that test return B but it returns 2. Generated IL code shows that information about enum type is lost and value passed to attribute is just 2.

Is there any way (I guess it should be some attribute) to preserve type in attribute value? Whats more interesting equivalent code in C# works as expected

Equivalent 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)
like image 762
Novakov Avatar asked Mar 01 '16 20:03

Novakov


1 Answers

I'm guessing and my knowledge on the internals of the compiler are actually quiet limited but I guess this is something to do with type inference. There is an equivalency between int <-> Enum, and I suspect that the type inference is reducing this to the lowest possible type, in this case int. You can fix this by doing the following

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)
like image 111
Colin Bull Avatar answered Sep 20 '22 16:09

Colin Bull