如何打开设置了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;
}
}
}
}
}