Home > OS >  How do I test if an enum is contained in a number?
How do I test if an enum is contained in a number?

Time:06-03

In VB6 I combine several DT_DRAW_FLAG values like this:

dim lMyFlags As DT_DRAW_FLAG
lMyFlags = DT_CENTER OR DT_VCENTER OR DT_RTLREADING

This would result in lMyFlags = 131077

Now to test if a certain flag is contained in such a combine flags value, I would do the following:

If (131077  And DT_RTLREADING) = DT_RTLREADING Then
    'DT_RTLREADING is contained. 
Else
    'DT_RTLREADING is NOT contained. 
End Enum

How would I do this in VB.NET?

Do I still have to use this "pure math" approach, or is there a method like...

lMyFlags.ContainsEnum(DT_RTLREADING)

... which I have not found yet?

Thank you!

CodePudding user response:

If you have an enum declaration like this

<Flags()> Public Enum DT_DRAW_FLAG As Integer
    DT_CENTER = 1
    DT_VCENTER = 2
    DT_RTLREADING = 4
End Enum

Then you can use HasFlag to do your logic

    Dim lMyFlags As DT_DRAW_FLAG = DT_DRAW_FLAG.DT_CENTER Or DT_DRAW_FLAG.DT_RTLREADING
    lMyFlags.HasFlag(DT_DRAW_FLAG.DT_RTLREADING) ' => true

The important point here is that the single enum values are powers of two.

CodePudding user response:

Accepted answer is good, it works. In your case, your Enum might already have the flags attribute, because it is a combination of three powers of 2: 2^0=1, 2^2=4, and 2^17=131072

Your enum may look like this

<Flags>
Public Enum DT_DRAW_FLAG As Long
    ''' <summary>
    ''' 2 ^ 0
    ''' </summary>
    DT_CENTER = 1
    ' 2 ^ 1 in here
    ''' <summary>
    ''' 2 ^ 4
    ''' </summary>
    DT_VCENTER = 4
    ' 2 ^ 3 through 2 ^ 16 in here
    ''' <summary>
    ''' 2 ^ 17
    ''' </summary>
    DT_RTLREADING = 131072
End Enum

The Flags Attribute

Indicates that an enumeration can be treated as a bit field; that is, a set of flags.

However, whether or not it has the Flags attribute, you can treat it the same way using bitwise And. I believe the HasFlags function is just shorthand for the bitwise logic:

' Bitwise logic
If (lMyFlags And DT_DRAW_FLAG.DT_RTLREADING) = DT_DRAW_FLAG.DT_RTLREADING Then
    ' Reading is contained
Else
    ' Reading is not contained
End If
' HasFlags
If lMyFlags.HasFlag(DT_DRAW_FLAG.DT_RTLREADING) Then
    ' Reading is contained
Else
    ' Reading is not contained
End If

It is certainly less code.

Note, you don't combine enums in the way that you have shown, without some additional conversion. Use bitwise Or to do that

Dim lMyFlags = DT_DRAW_FLAG.DT_CENTER Or DT_DRAW_FLAG.DT_VCENTER Or DT_DRAW_FLAG.DT_RTLREADING

Also, you can use Enum.HasFlag regardless of whether you used the Flags Attribute. As far as I know, the attribute is just used to signal to the consumer that the values are distinct powers of two, and bitwise logic can be performed on them. There is nothing strictly going on with the flags attribute so there's some trust in the consumer to know what to do with it (and we assume the original author knew about it, too)

  • Related