Default property for reading and setting bit flags
- Dominant language
- No language data
- Stars
- 328
- Forks
- 71
- PR merge metrics
- No merged PRs in 30d
Description
Bit twiddling to check and set flags is arcane. Given a flag enumeration of the form:
``` VB.NET
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:
``` VB.NET
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:
``` VB.NET
value = (value Or Color.Red)
```
To set it to off you AND it with the negation of the flag (I think):
``` VB.NET
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 `` 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:
``` VB.NET
' 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:
``` VB.NET
value(Color.Red) = True
```
To set it to off you set the bits at that mask to false:
``` VB.NET
value(Color.Red) = 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 `Or`ing the values:
``` VB.NET
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.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the VB.NET examples and the existing 38-comment discussion, since the issue names no implementation files or tests. Determine whether the proposed default-property behavior and queryable binding compatibility have an accepted language design; done would require a resolved specification before implementation can begin.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- visualbasic
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100