116 lines
3.9 KiB
Plaintext
116 lines
3.9 KiB
Plaintext
== Why is this an issue?
|
|
|
|
An enumeration can be decorated with the https://learn.microsoft.com/en-us/dotnet/api/system.flagsattribute[FlagsAttribute] to indicate that it can be used as a https://en.wikipedia.org/wiki/Bit_field[bit field]: a set of flags, that can be independently set and reset.
|
|
|
|
For example, the following definition of the day of the week:
|
|
|
|
[source,vbnet]
|
|
----
|
|
<Flags()>
|
|
Enum Days
|
|
Monday = 1 ' 0b00000001
|
|
Tuesday = 2 ' 0b00000010
|
|
Wednesday = 4 ' 0b00000100
|
|
Thursday = 8 ' 0b00001000
|
|
Friday = 16 ' 0b00010000
|
|
Saturday = 32 ' 0b00100000
|
|
Sunday = 64 ' 0b01000000
|
|
End Enum
|
|
----
|
|
|
|
allows to define special set of days, such as `WeekDays` and `Weekend` using the `Or` operator:
|
|
|
|
[source,vbnet]
|
|
----
|
|
<Flags()>
|
|
Enum Days
|
|
' ...
|
|
None = 0 ' 0b00000000
|
|
Weekdays = Monday Or Tuesday Or Wednesday Or Thursday Or Friday ' 0b00011111
|
|
Weekend = Saturday Or Sunday ' 0b01100000
|
|
All = Weekdays Or Weekend ' 0b01111111
|
|
End Enum
|
|
----
|
|
|
|
These can be used to write more expressive conditions, taking advantage of https://learn.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/operators-and-expressions/logical-and-bitwise-operators#bitwise-operations[bitwise operators] and https://learn.microsoft.com/en-us/dotnet/api/system.enum.hasflag[Enum.HasFlag]:
|
|
|
|
[source,vbnet]
|
|
----
|
|
Dim someDays = Days.Wednesday | Days.Weekend ' 0b01100100
|
|
someDays.HasFlag(Days.Wednesday) ' someDays contains Wednesday
|
|
|
|
Dim mondayAndWednesday = Days.Monday Or Days.Wednesday
|
|
someDays.HasFlag(mondayAndWednesday) ' someDays contains Monday and Wednesday
|
|
someDays.HasFlag(Days.Monday) OrElse someDays.HasFlag(Days.Wednesday) ' someDays contains Monday or Wednesday
|
|
someDays And Days.Weekend <> Days.None ' someDays overlaps with the weekend
|
|
someDays And Days.Weekdays = Days.Weekdays ' someDays is only made of weekdays
|
|
----
|
|
|
|
Consistent use of `None` in flag enumerations indicates that all flag values are cleared. The value 0 should not be used to indicate any other state since there is no way to check that the bit `0` is set.
|
|
|
|
[source,vbnet]
|
|
----
|
|
<Flags()>
|
|
Enum Days
|
|
Monday = 0 ' 0 is used to indicate Monday
|
|
Tuesday = 1
|
|
Wednesday = 2
|
|
Thursday = 4
|
|
Friday = 8
|
|
Saturday = 16
|
|
Sunday = 32
|
|
Weekdays = Monday Or Tuesday Or Wednesday Or Thursday Or Friday
|
|
Weekend = Saturday Or Sunday
|
|
All = Weekdays Or Weekend
|
|
End Enum
|
|
|
|
Dim someDays = Days.Wednesday Or Days.Thursday
|
|
someDays & Days.Tuesday = Days.Tuesday ' False, because someDays doesn't contains Tuesday
|
|
someDays & Days.Monday = Days.Monday ' True, even though someDays doesn't contains Monday!
|
|
someDays.HasFlag(Days.Monday) ' Same issue as above
|
|
----
|
|
|
|
== How to fix it
|
|
|
|
=== Code examples
|
|
|
|
==== Noncompliant code example
|
|
|
|
[source,vbnet,diff-id=1,diff-type=noncompliant]
|
|
----
|
|
<Flags()>
|
|
Enum FruitType
|
|
Void = 0 ' Non-Compliant
|
|
Banana = 1
|
|
Orange = 2
|
|
Strawberry = 4
|
|
End Enum
|
|
----
|
|
|
|
==== Compliant solution
|
|
|
|
[source,vbnet,diff-id=1,diff-type=compliant]
|
|
----
|
|
<Flags()>
|
|
Enum FruitType
|
|
None = 0 ' Compliant
|
|
Banana = 1
|
|
Orange = 2
|
|
Strawberry = 4
|
|
End Enum
|
|
----
|
|
|
|
== Resources
|
|
|
|
=== Documentation
|
|
|
|
* https://learn.microsoft.com/en-us/dotnet/api/system.flagsattribute[FlagsAttribute]
|
|
* https://en.wikipedia.org/wiki/Bit_field[Bit field]
|
|
* https://learn.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/operators-and-expressions/logical-and-bitwise-operators#bitwise-operations[Logical and Bitwise Operators in Visual Basic]
|
|
* https://learn.microsoft.com/en-us/dotnet/api/system.enum.hasflag[Enum.HasFlag(Enum) Method]
|
|
|
|
=== Articles & blog posts
|
|
|
|
* https://learn.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/ms229062(v=vs.100)[Designing Flags Enumerations]
|
|
|
|
include::../rspecator.adoc[] |