如何打开设置了flags属性的枚举(或更确切地说,用于位操作)?

我希望能够在匹配声明值的开关中找到所有情况。

问题是,如果我有以下枚举

[Flags()]public enum CheckType
{
    Form = 1,
    QueryString = 2,
    TempData = 4,
}

我想使用这样的开关
switch(theCheckType)
{
   case CheckType.Form:
       DoSomething(/*Some type of collection is passed */);
       break;

   case CheckType.QueryString:
       DoSomethingElse(/*Some other type of collection is passed */);
       break;

   case CheckType.TempData
       DoWhatever(/*Some different type of collection is passed */);
       break;
}

如果“theCheckType”设置为两个CheckType.Form | CheckType.TempData我希望它能同时击中两种情况。显然,由于中断,它不会在我的示例中同时命中,但除此之外,它也会失败,因为CheckType.Form不等于CheckType.Form |。 CheckType.TempData

正如我所看到的,唯一的解决方案是为枚举值的每种可能组合辩护?

就像是
    case CheckType.Form | CheckType.TempData:
        DoSomething(/*Some type of collection is passed */);
        DoWhatever(/*Some different type of collection is passed */);
        break;

    case CheckType.Form | CheckType.TempData | CheckType.QueryString:
        DoSomething(/*Some type of collection is passed */);
        DoSomethingElse(/*Some other type of collection is passed */);
        break;

... and so on...

但这确实不是很理想(因为它将很快变得很大)

现在我有3个条件

就像是
if ((_CheckType & CheckType.Form) != 0)
{
    DoSomething(/*Some type of collection is passed */);
}

if ((_CheckType & CheckType.TempData) != 0)
{
    DoWhatever(/*Some type of collection is passed */);
}

....

但这也意味着,如果我有一个带有20个值的枚举,则每次必须经过20个If条件,而不是像使用开关时那样仅“跳转”到所需的“case”/。

有解决这个问题的魔术方法吗?

我已经考虑过循环遍历声明的值然后使用开关的可能性,然后它将仅对每个声明的值命中该开关,但是我不知道它将如何工作以及如果它对性能有不利影响(相比许多如果)?

有没有一种简单的方法可以遍历声明的所有枚举值?

我只能提出使用ToString()并按“,”分割,然后遍历数组并解析每个字符串。

更新:

我看到我的解释还不够好。
我的示例很简单(试图简化我的方案)。

我将它用于Asp.net MVC中的ActionMethodSelectorAttribute,以确定在解析url/route时是否应该可用的方法。

我通过在方法上声明这样的东西来做到这一点
[ActionSelectorKeyCondition(CheckType.Form | CheckType.TempData, "SomeKey")]
public ActionResult Index()
{
    return View();
}

这意味着它应该检查Form或TempData是否具有为可用方法指定的键。

它将要调用的方法(在我之前的示例中为doSomething(),doSomethingElse()和doWhatever())实际上将bool作为返回值,并将使用参数进行调用(不同的集合不共享可共享的接口(interface))使用-请在下面的链接中查看我的示例代码,等等)。

为了希望更好地了解我在做什么,我粘贴了一个我实际上在pastebin上正在做的简单示例-可以在这里找到http://pastebin.com/m478cc2b8

最佳答案

这个怎么样。当然,DoSomething的参数和返回类型等可以是您喜欢的任何东西。

class Program
{
    [Flags]
    public enum CheckType
    {
        Form = 1,
        QueryString = 2,
        TempData = 4,
    }

    private static bool DoSomething(IEnumerable cln)
    {
        Console.WriteLine("DoSomething");
        return true;
    }

    private static bool DoSomethingElse(IEnumerable cln)
    {
        Console.WriteLine("DoSomethingElse");
        return true;
    }

    private static bool DoWhatever(IEnumerable cln)
    {
        Console.WriteLine("DoWhatever");
        return true;
    }

    static void Main(string[] args)
    {
        var theCheckType = CheckType.QueryString | CheckType.TempData;
        var checkTypeValues = Enum.GetValues(typeof(CheckType));
        foreach (CheckType value in checkTypeValues)
        {
            if ((theCheckType & value) == value)
            {
                switch (value)
                {
                    case CheckType.Form:
                        DoSomething(null);
                        break;
                    case CheckType.QueryString:
                        DoSomethingElse(null);
                        break;
                    case CheckType.TempData:
                        DoWhatever(null);
                        break;
                }
            }
        }
    }
}

08-04 22:13