Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to create a generic bitwise enumeration 'IsOptionSet()' method?

The below code makes it easy to pass in a set HtmlParserOptions and then check against a single option to see if it's been selected.

[Flags]
public enum HtmlParserOptions
{
    NotifyOpeningTags = 1,
    NotifyClosingTags = 2,
    NotifyText = 4,
    NotifyEmptyText = 8
}

private bool IsOptionSet(HtmlParserOptions options, HtmlParserOptions singleOption)
{
    return (options & singleOption) == singleOption;
}

My question is, is it possible to create a Generic version of this (I'm guessing through implementing an interface on the method properties) that will work with any enumeration with the Flags attribute?

like image 413
Peter Bridger Avatar asked Dec 13 '22 01:12

Peter Bridger


1 Answers

Edit:

The easiest, nicest option is to upgrade to VS2010 Beta2 and use .NET 4's Enum.HasFlag method. The framework team has added a lot of nice additions to Enum to make them nicer to use.


Original (for current .NET):

You can do this by passing Enum, instead of generics:

static class EnumExtensions
{
    private static bool IsSignedTypeCode(TypeCode code)
    {
        switch (code)
        {
            case TypeCode.Byte:
            case TypeCode.UInt16:
            case TypeCode.UInt32:
            case TypeCode.UInt64:
                return false;
            default:
                return true;
        }
    }

    public static bool IsOptionSet(this Enum value, Enum option)
    {
        if (IsSignedTypeCode(value.GetTypeCode()))
        {
            long longVal = Convert.ToInt64(value);
            long longOpt = Convert.ToInt64(option);
            return (longVal & longOpt) == longOpt;
        }
        else
        {
            ulong longVal = Convert.ToUInt64(value);
            ulong longOpt = Convert.ToUInt64(option);
            return (longVal & longOpt) == longOpt;
        }
    }
}

This works perfectly, like so:

class Program
{
    static void Main(string[] args)
    {
        HtmlParserOptions opt1 = HtmlParserOptions.NotifyText | HtmlParserOptions.NotifyEmptyText;
        Console.WriteLine("Text: {0}", opt1.IsOptionSet(HtmlParserOptions.NotifyText));
        Console.WriteLine("OpeningTags: {0}", opt1.IsOptionSet(HtmlParserOptions.NotifyOpeningTags));

        Console.ReadKey();
    } 
}

THe above prints:

Text: True
OpeningTags: False

The downside to this, though, is it doesn't protect you from passing two different types of Enum types into the routine. You have to use it reasonably.

like image 179
Reed Copsey Avatar answered Dec 16 '22 18:12

Reed Copsey