Click here to Skip to main content
13,200,202 members (60,595 online)
Click here to Skip to main content
Add your own
alternative version


121 bookmarked
Posted 7 Jul 2009

Enums, Flags, and C# — Oh My! (Bad Pun…)

, 3 Sep 2009
Rate this:
Please Sign up or sign in to vote.
How you can use Enumerated types and the Flag Attribute along with Extension Methods to make your code more compact and easier to understand

I’m not sure about everyone else, but I just love Enumerated types. What's more, I love the Flags Attribute when you combine them together. This post explores how you can use these two things along with Extension Methods to make your code more compact and easier to understand.

If you’ve never used this combination before, then you’re missing out. Consider the following code…

class User {
    bool CanDelete;
    bool CanRead;
    bool CanWrite;
    bool CanModify;
    bool CanCreate;

Okay, so that’s no big deal even though it may be quite a few extra lines of code. It would be nice to be able to combine all of those permissions into a single value. That’s where an Enumerated Type with a FlagAttribute comes in.

enum PermissionTypes : int {
    None = 0,
    Read = 1,
    Write = 2,
    Modify = 4,
    Delete = 8
    Create = 16,
    All = Read | Write | Modify | Delete | Create

//and the class from before
class User {
    PermissionTypes Permissions = PermissionTypes.None;

Excellent…. So Now What?

So now, what's great about this is we can assign multiple values onto the same property. Not only that, we can also check for existing values with a (strange) comparison.

//create a new user
User admin = new User();
admin.Permissions = PermissionTypes.Read
    | PermissionTypes.Write
    | PermissionTypes.Delete;

//check for permissions
bool canRead = ((PermissionTypes.Read & admin.Permissions) == PermissionTypes.Read);
bool canWrite = ((PermissionTypes.Write & admin.Permissions) == PermissionTypes.Write);
bool canCreate = ((PermissionTypes.Create & admin.Permissions) == PermissionTypes.Create);

//and the results
Console.WriteLine(canRead); //true
Console.WriteLine(canWrite); //true
Console.WriteLine(canCreate); //false

Now shorter and easier to read — sorta. See that really odd comparison? That’s what you need to write each time you want to check for a value. It’s not that bad, but it isn’t really something I’d like to type very often. You could write a separate function to do these comparisons for you, but we can do even better than that.

Taking Advantage of Extension Methods

Since an Enumerated Type isn’t really a class, you can’t extend methods onto them. However, you can extend methods onto the class System.Enum. Methods added to this class will appear in the methods for all of your enumerated types!

Here is an example method…

//full class included at the end of the post
public static class EnumerationExtensions {

    //checks to see if an enumerated value contains a type
    public static bool Has<T>(this System.Enum type, T value) {
        try {
            return (((int)(object)type & 
              (int)(object)value) == (int)(object)value);
        catch {
            return false;

Now, this code does make an assumption that it can cast your Enumerated Type to an integer. You could do some type checking before you do the comparisons, but for the sake of this example, we’re going to keep this short.

So, just how do you use this extension?

//start with a value
PermissionTypes permissions = PermissionTypes.Read | PermissionTypes.Write;

//then check for the values
bool canRead = permissions.Has(PermissionTypes.Read); //true
bool canWrite = permissions.Has(PermissionTypes.Write); //true
bool canDelete = permissions.Has(PermissionTypes.Delete); //false

Now, that is much easier to read! Even better, you’ll notice despite the fact this has a Generic parameter, we don’t have to provide the type at the start since the method can infer it from the parameter (implicitly typed parameters — sweeeeet!).

And don’t forget, System.Enum isn’t the only class you can do this with, there are other classes (like System.Array, for example) that you can add your own extension methods to for surprising results!

As I stated before, this doesn't cover all cases of what you could expect - this code should be modified depending on how you plan to use it. For example, if you're using long, uint, ulong, this code won't cover all of your cases.

You may also wonder why we cast to an object before we cast to an int. When you're working with Generics, you can't cast to a value (non-nullable) type immediately, you have to either cast to an object and then to a value type, or just cast directly to a nullable value type, such as int.

Below is the full source code for the EnumerationExtensions class. If you have any improvements, please let me know! I'm currently working on a revised version to improve this code.

namespace Enum.Extensions {

    public static class EnumerationExtensions {

        //checks if the value contains the provided type
        public static bool Has<T>(this System.Enum type, T value) {
            try {
                return (((int)(object)type & (int)(object)value) == (int)(object)value);
            catch {
                return false;

        //checks if the value is only the provided type
        public static bool Is<T>(this System.Enum type, T value) {
            try {
                return (int)(object)type == (int)(object)value;
            catch {
                return false;

        //appends a value
        public static T Add<T>(this System.Enum type, T value) {
            try {
                return (T)(object)(((int)(object)type | (int)(object)value));
            catch(Exception ex) {
                throw new ArgumentException(
                        "Could not append value from enumerated type '{0}'.",
                        ), ex);

        //completely removes the value
        public static T Remove<T>(this System.Enum type, T value) {
            try {
                return (T)(object)(((int)(object)type & ~(int)(object)value));
            catch (Exception ex) {
                throw new ArgumentException(
                        "Could not remove value from enumerated type '{0}'.",
                        ), ex);


This article, along with any associated source code and files, is licensed under The Creative Commons Attribution-ShareAlike 2.5 License


About the Author

United States United States
No Biography provided

You may also be interested in...

Comments and Discussions

SuggestionIn addition Pin
memberSQUALLYGATOR4-Dec-13 3:49 
Question5 Pin
.NetStars6-Feb-13 22:04
member.NetStars6-Feb-13 22:04 
GeneralMy vote of 5 Pin
.NetStars6-Feb-13 22:04
member.NetStars6-Feb-13 22:04 
GeneralMy vote of 5 Pin
MBigglesworth798-Jun-11 21:28
memberMBigglesworth798-Jun-11 21:28 
GeneralI think .NET 4 enum has some new stuff Pin
Sacha Barber9-Apr-11 21:45
mvpSacha Barber9-Apr-11 21:45 
GeneralMy vote of 5 Pin
Eddy Vluggen2-Feb-11 23:34
memberEddy Vluggen2-Feb-11 23:34 
Generalnice one Pin
Pranay Rana17-Dec-10 1:12
memberPranay Rana17-Dec-10 1:12 
GeneralMy vote of 5 Pin
Varun Sareen19-Aug-10 0:10
memberVarun Sareen19-Aug-10 0:10 
GeneralCompile time type safety [modified] Pin
Espen Røvik Larsen10-Feb-10 22:07
memberEspen Røvik Larsen10-Feb-10 22:07 
GeneralRe: Compile time type safety Pin
Espen Røvik Larsen11-Feb-10 8:13
memberEspen Røvik Larsen11-Feb-10 8:13 
I realize C# can not have System.Enum as a constraint on generic parameters. Interfaces works fine - though System.Enum doesn't implement one single interface that makes it unique it does implement three different interfaces - this should be good enough :

public static bool Has<t>(this T type, T value) where T : IComparable, IConvertible, IFormattable
GeneralWordy bit test Pin
SAKryukov11-Jan-10 6:32
memberSAKryukov11-Jan-10 6:32 
GeneralRe: Wordy bit test Pin
stixoffire26-Feb-15 5:02
memberstixoffire26-Feb-15 5:02 
GeneralRe: Wordy bit test Pin
Sergey Alexandrovich Kryukov26-Feb-15 5:07
mvpSergey Alexandrovich Kryukov26-Feb-15 5:07 
GeneralVery good Pin
AuroreC4-Oct-09 21:46
memberAuroreC4-Oct-09 21:46 
GeneralPerformance & Type check Pin
Gildor_haohao8-Sep-09 21:10
memberGildor_haohao8-Sep-09 21:10 
GeneralException handling smell Pin
Nathan Allan8-Sep-09 6:09
memberNathan Allan8-Sep-09 6:09 
GeneralUmmmm....... Pin
tonyt7-Sep-09 19:52
membertonyt7-Sep-09 19:52 
GeneralRe: Ummmm....... Pin
webdev_hb8-Sep-09 2:18
memberwebdev_hb8-Sep-09 2:18 
GeneralGood one Pin
N a v a n e e t h3-Sep-09 7:31
mvpN a v a n e e t h3-Sep-09 7:31 
QuestionRe: Good one Pin
stixoffire26-Feb-15 5:05
memberstixoffire26-Feb-15 5:05 
Generalvery cool! Pin
DetoX833-Sep-09 6:56
memberDetoX833-Sep-09 6:56 
GeneralFYI: extension method in VB.NET [modified] Pin
Shimmy Weitzhandler17-Aug-09 22:51
memberShimmy Weitzhandler17-Aug-09 22:51 
GeneralRe: FYI: extension method in VB.NET Pin
Hanzie537-Sep-09 21:47
memberHanzie537-Sep-09 21:47 
GeneralRe: FYI: extension method in VB.NET Pin
Shimmy Weitzhandler8-Sep-09 11:23
memberShimmy Weitzhandler8-Sep-09 11:23 
Questionmixing different enumtypes ? Pin
Frank Jurisch29-Jul-09 0:50
memberFrank Jurisch29-Jul-09 0:50 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.171020.1 | Last Updated 3 Sep 2009
Article Copyright 2009 by webdev_hb
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid