Search code examples
enumscastingf#type-conversionflags

Cast integer to enum type with Flags attribute


I have an enum type with the flags attribute:

[<Flags>]
type StatusWord =
    | DATAPROCESS       = 0b0000000001
    | ERRORPRESENT      = 0b0000000010
    | CHECKSUMERROR     = 0b0000000100
    | PACKETSIZEERROR   = 0b0000001000
    | TIMEOUT           = 0b0000010000
    | DONOTRETRY        = 0b1000000000

and during some data initialization, I have a uint16 value I want to convert to the enum's type, StatusWord, so I can compare it's properties:

let value: uint16 = 0b1000001001us
let flags: StatusWord = StatusWord value

but, as you might be able to guess, this code doesn't compile; the conversion isn't available. Likewise, I also can't do explicit casts, eg. value :> StatusWord or value :?> StatusWord. This is a simple task in C#, so I'm having trouble figuring out why I can't do it in F#.


Solution

  • So, two things you have to worry about. One (which I think you already realize) is that your underlying enum type is int32, and your value is uint16, so a conversion will need to happen somewhere. Two, you have to construct the enum type.

    StatusWord looks like a constructor (similar to a union case member), but it's not. So here are two ways to do it with your uint16 value, and a third way to do it which is much better for readability, if you can do it that way.

    let value = 0b1000001001us
    
    // use F# enum operator
    let flags1 = enum<StatusWord> (int value)
    
    // use static Enum class
    let flags2 = Enum.Parse(typeof<StatusWord>, string value) :?> StatusWord
    
    // do bitwise stuff, of course now the compiler knows what you're doing
    let flags3 = StatusWord.DATAPROCESS ||| StatusWord.PACKETSIZEERROR ||| StatusWord.DONOTRETRY
    

    Because there are multiple ways, I had to refresh my memory, which I did at

    https://fsharpforfunandprofit.com/posts/enum-types/

    which is highly recommended reading (that article and the rest of that blog - it's how many people learn F#).