Enum.HasFlag: good or bad?

2011/01/28

no comments

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
  1. public enum MyEnum
  2. {
  3.     None = 0,
  4.     A = 1,
  5.     B = 2,
  6.     C = 4,
  7.     D = 8
  8. }

we can use the bitwise for checking whether instantiation of

the enum contain a value, as shown in the next snippet:

Code Snippet
  1. var options = MyEnum.A | MyEnum.B;
  2. if ((options & MyEnum.A) == MyEnum.A)
  3. {
  4.     // Do something
  5. }

.NET 4 come with elegant syntax which look like the following:

Code Snippet
  1. var options = MyEnum.A | MyEnum.B;
  2. if (options.HasFlag (MyEnum.A))
  3. {
  4.     // Do something
  5. }

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:

Enum, HasFlags, flags, C#, .NET

the full code for this test can be find at:

http://codepaste.net/9jtz98

 

basically it compare

Code Snippet
  1. for (int i = 0; i < 1000000; i++)
  2. {
  3.     var hasOption = (options & MyEnum.A) == MyEnum.A;
  4.     hasFlag = hasFlag && hasOption;
  5. }

with

Code Snippet
  1. for (int i = 0; i < 1000000; i++)
  2. {
  3.     var hasOption = options.HasFlag(MyEnum.A);
  4.     hasFlag = hasFlag && hasOption;
  5. }

 

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
  1. public bool HasFlag(Enum flag)
  2. {
  3.     if (!base.GetType().IsEquivalentTo(flag.GetType()))
  4.     {
  5.         throw new ArgumentException(Environment.GetResourceString("Argument_EnumTypeDoesNotMatch", new object[] { flag.GetType(), base.GetType() }));
  6.     }
  7.     ulong num = ToUInt64(flag.GetValue());
  8.     return ((ToUInt64(this.GetValue()) & num) == num);
  9. }

 

kick it on DotNetKicks.com

Digg This
Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>