DEV Community

Cover image for Save nanoseconds with a quicker Enum.HasFlag
Adam K Dean
Adam K Dean

Posted on

Save nanoseconds with a quicker Enum.HasFlag

One of the easiest ways to manage security flags is to have an Enum and use bitwise comparisons, however you would expect .NET to make things a bit easier for you, afterall who wants to start littering the code with bitwise expressions?

.NET does actually make it easier for you, allowing you to check flags with the Enum.HasFlag method, but it has type checking and is generally slow. Like running through water slow.

Let's make a enum to begin with:

[Flags]
public enum UserFlag
{
    User = 1,
    Moderator = 2,
    Administrator = 4,
    Developer = 8
}
Enter fullscreen mode Exit fullscreen mode

We can now give a hypothetical User some flags. We could make them just a User, or a User and a Moderator. We could make them all four. Let's just make them a user with moderation rights, a pretty popular choice.

UserFlag flags = UserFlag.User | UserFlag.Moderator;
Enter fullscreen mode Exit fullscreen mode

If we were to have a section that only allowed moderators in, we could perform a check with bitwise:

if ((flags & UserFlag.Moderator) == UserFlag.Moderator)
{
    ...
}
Enter fullscreen mode Exit fullscreen mode

Easy, but maybe confusing to a newbie reading the code. An easier way would be to use HasFlag:

if (flags.HasFlag(UserFlag.Moderator))
{
    ...
}
Enter fullscreen mode Exit fullscreen mode

Running through water, fully dressed whilst carrying a basket of bread. The reason that HasFlag is so slow is because of type checking, we really don't need that in place, we know the type, we just want the check made. An easier way would be to have an extension method:

public static class UserFlagExtensions
{
    public static bool HasFlagQuick(this UserFlag haystack, UserFlag needle)
    {
        return (haystack & needle) == needle;
    }
}
Enter fullscreen mode Exit fullscreen mode

How much quicker is this you may ask? I ran the check ten million times each, and the results are pretty visible. Removing the needless type checking gives us a method that is 15 times quicker, saving us 32.8 nanoseconds per call.

Method         Count        Elapsed Total   Elapsed Each
HasFlag        10,000,000   0.390 s         39.0 nano seconds
HasFlagQuick   10,000,000   0.062 s          6.2 nano seconds
Enter fullscreen mode Exit fullscreen mode

Top comments (0)