Enum.HasFlag: good or bad?
Enum.HasFlag: good or bad?
.NET 4 give us nice elegant way of checking whether [Flags] enums
contain a value.
assuming that we have the following enum:
Code Snippet
- public enum MyEnum
- {
- None = 0,
- A = 1,
- B = 2,
- C = 4,
- D = 8
- }
we can use the bitwise for checking whether instantiation of
the enum contain a value, as shown in the next snippet:
Code Snippet
- var options = MyEnum.A | MyEnum.B;
- if ((options & MyEnum.A) == MyEnum.A)
- {
- // Do something
- }
.NET 4 come with elegant syntax which look like the following:
Code Snippet
- var options = MyEnum.A | MyEnum.B;
- if (options.HasFlag (MyEnum.A))
- {
- // Do something
- }
whether it good or bad to use the new syntax we will discover soon,
anyway it is surely not ugly.
What's the problem with this syntax?
the problem with the syntax is that it is not syntactic sugar (as we might thought).
as elegant and convenient it is, it is hiding reflection operations (GetType()).
using this syntax under intensive iteration you may lead to performance hit.
the following output show the effect of having Enum.HasFlag inside intensive iteration:

the full code for this test can be find at:
http://codepaste.net/9jtz98
basically it compare
Code Snippet
- for (int i = 0; i < 1000000; i++)
- {
- var hasOption = (options & MyEnum.A) == MyEnum.A;
- hasFlag = hasFlag && hasOption;
- }
with
Code Snippet
- for (int i = 0; i < 1000000; i++)
- {
- var hasOption = options.HasFlag(MyEnum.A);
- hasFlag = hasFlag && hasOption;
- }
Summary
Enum.HasFlag is definitely slower than the bitwise comparison, but it is cleaner
and more readable.
therefore I may argue that it is OK to use it unless it is under intensive iteration.
point of interest
the implementation of Enum.HasFlag is:
Code Snippet
- public bool HasFlag(Enum flag)
- {
- if (!base.GetType().IsEquivalentTo(flag.GetType()))
- {
- throw new ArgumentException(Environment.GetResourceString("Argument_EnumTypeDoesNotMatch", new object[] { flag.GetType(), base.GetType() }));
- }
- ulong num = ToUInt64(flag.GetValue());
- return ((ToUInt64(this.GetValue()) & num) == num);
- }