Bit twiddling to check and set flags is arcane. Given a flag enumeration of the form:
<Flags>
Enum Color
Red = 1
Green = 2
Blue = 4
End Enum
To check whether a flag (or set of flags) is set you AND the bit mask with the value and compare it to itself:
Dim isRed = ((value And Color.Red) = Color.Red)
Dim isYellow = (value And (Color.Red Or Color.Green)) = (Color.Red Or Color.Green))
To set a flag on you OR the value with the mask:
value = (value Or Color.Red)
To set it to off you AND it with the negation of the flag (I think):
value = (value And Not Color.Red)
It also has this unfortunate side-effect that to see if both Red and Green are set you have to Or them. None of this is intuitive, fun, or memorable, and it lacks VB's brand of straightforward approachability. I propose that instead of forcing VB users to remember this low-level operations, adding an implicit default property to all the integral numeric types and any <Flags> enumerated types which takes a mask and returns true if the specified bits are on and false if they aren't and which lets you set the bits in the supplied mask to on or off.
To check whether a flag (or set of flags) is set you just index the value with the flag:
' Explicitly comparing to True for clarity
If value(Color.Red) = True Then
' Red.
End If
To set a flag on you set "the bit(s)" at that mask to true:
To set it to off you set the bits at that mask to false:
And the neat thing is that it's concise enough that if you want to check for more than one flag you can And the individual checks instead of Oring the values:
If value(Color.Red) = True AndAlso value(Color.Green) = True Then
' Yellow.
ElseIf value(Color.Red) = True OrElse value(Color.Green) = True Then
' I don't know why one would check this.
End If
That's much better, I think. I don't have to remember anything. The System.Enum.HasFlags method was added in .NET 4.0 to make this simpler but it uses reflection, is comparatively slow, and isn't strongly-typed. One could write extension methods but you'd need to do this on a per-type basis. BitVector32 is compact and speedy but not strongly-typed and limited to 32-bit integer stores. BitArray has a variable capacity but allocates a lot. With this we can keep the size and performance characteristics of using the integral types directly with strong typing and the compiler can optimize the Or and And cases for constants so that it has the same performance as the code you would write today.
Breaking Change
This could technically be a very minor breaking change because VB today lets you define an "extension readonly default property" on any type by defining an ElementAtOrDefault extension function and a Select extension method to make it a queryable type. There is no way to emulate the case of making the default property writeable.
This entire scenario seems extremely unlikely but the breaking change could be avoided entirely by binding this way only after the queryable/ElementAtOrDefault check fails.
Bit twiddling to check and set flags is arcane. Given a flag enumeration of the form:
To check whether a flag (or set of flags) is set you AND the bit mask with the value and compare it to itself:
To set a flag on you OR the value with the mask:
To set it to off you AND it with the negation of the flag (I think):
It also has this unfortunate side-effect that to see if both
RedandGreenare set you have toOrthem. None of this is intuitive, fun, or memorable, and it lacks VB's brand of straightforward approachability. I propose that instead of forcing VB users to remember this low-level operations, adding an implicit default property to all the integral numeric types and any<Flags>enumerated types which takes a mask and returns true if the specified bits are on and false if they aren't and which lets you set the bits in the supplied mask to on or off.To check whether a flag (or set of flags) is set you just index the value with the flag:
To set a flag on you set "the bit(s)" at that mask to true:
To set it to off you set the bits at that mask to false:
And the neat thing is that it's concise enough that if you want to check for more than one flag you can
Andthe individual checks instead ofOring the values:That's much better, I think. I don't have to remember anything. The
System.Enum.HasFlagsmethod was added in .NET 4.0 to make this simpler but it uses reflection, is comparatively slow, and isn't strongly-typed. One could write extension methods but you'd need to do this on a per-type basis.BitVector32is compact and speedy but not strongly-typed and limited to 32-bit integer stores.BitArrayhas a variable capacity but allocates a lot. With this we can keep the size and performance characteristics of using the integral types directly with strong typing and the compiler can optimize theOrandAndcases for constants so that it has the same performance as the code you would write today.Breaking Change
This could technically be a very minor breaking change because VB today lets you define an "extension readonly default property" on any type by defining an
ElementAtOrDefaultextension function and aSelectextension method to make it a queryable type. There is no way to emulate the case of making the default property writeable.This entire scenario seems extremely unlikely but the breaking change could be avoided entirely by binding this way only after the queryable/ElementAtOrDefault check fails.