打开枚举(带Flags属性),而不声明每一个可能的组合? [英] Switch on Enum (with Flags attribute) without declaring every possible combination?

查看:143
本文介绍了打开枚举(带Flags属性),而不声明每一个可能的组合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我如何打开一个具有flags属性集的枚举(或更精确地用于位操作)?



我想要能够全部打



问题是如果我有以下枚举

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

我想使用这样的开关

  switch(theCheckType)
{
case CheckType.Form:
DoSomething(/ *某些类型的集合被传递* /);
break;

case CheckType.QueryString:
DoSomethingElse(/ *某些其他类型的集合被传递* /);
break;

case CheckType.TempData
DoWhatever(/ *一些不同类型的集合被传递* /);
break;
}

如果theCheckType设置为CheckType.Form | CheckType.TempData我想要它打两个case的。显然,它不会在我的例子中打中两个,因为中断,但除此之外它也失败,因为CheckType.Form不等于CheckType.Form | CheckType.TempData



我可以看到唯一的解决方案是为每个可能的枚举值组合提供一个案例?



  case CheckType.Form | CheckType.TempData:
DoSomething(/ *某些类型的集合被传递* /);
DoWhatever(/ *某些不同类型的集合被传递* /);
break;

case CheckType.Form | CheckType.TempData | CheckType.QueryString:
DoSomething(/ *某些类型的集合被传递* /);
DoSomethingElse(/ *某些其他类型的集合被传递* /);
break;

...等等...

但是真的isnt非常希望(因为它会快速增长很大)



现在我有3如果条件恰恰相反,



  if((_CheckType& CheckType.Form)!= 0)
{
DoSomething(/ *某些类型的集合被传递* /);
}

如果((_CheckType& CheckType.TempData)!= 0)
{
DoWhatever(/ *某些类型的集合被传递* /);
}

....

但这也意味着如果我有一个具有20个值的枚举,它必须经过20,如果条件每一次,而不是跳转,只需要使用切换所需的案例/。



有没有一些魔法解决方案来解决这个问题?



我想到了循环遍历声明值的可能性,然后使用开关,然后它只会为所宣称的每个值触发切换,但是我不知道它会如何工作,如果性能恶化是一个好主意(与很多if相比较)?



/ p>

我只能用ToString()和,分开,然后循环遍历数组并解析每个字符串。






更新:


$ b $我看到我没有做好足够的工作解释。
我的例子是简单(试图简化我的场景)。



我在Asp.net MVC中使用它作为ActionMethodSelectorAttribute来确定一个方法是否应该解决URL /路由时可用。



我通过在方法中声明这样的方式

  [ActionSelectorKeyCondition(CheckType.Form | CheckType.TempData,SomeKey)] 
public ActionResult Index()
{
return View();
}

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



它将调用的方法(doSomething(),doSomethingElse()和doWhatever()在我前面的例子中)实际上将bool作为返回值,并将被调用一个参数(不同的集合,不共享可以使用的接口 - 请参见下面的链接中的示例代码等)。



希望能够更好地了解我在做什么我已经粘贴了一个简单的例子,我在实际上在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);
返回true;
}

private static bool DoSomethingElse(IEnumerable cln)
{
Console.WriteLine(DoSomethingElse);
返回true;
}

private static bool DoWhatever(IEnumerable cln)
{
Console.WriteLine(DoWhatever);
返回true;
}

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


how do i switch on an enum which have the flags attribute set (or more precisely is used for bit operations) ?

I want to be able to hit all cases in a switch that matches the values declared.

The problem is that if i have the following enum

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

and I want to use a switch like this

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;
}

If "theCheckType" is set to both CheckType.Form | CheckType.TempData I want it to hit both case's. Obviously it wont hit both in my example because of the break, but other than that it also fails because CheckType.Form is not equal to CheckType.Form | CheckType.TempData

The only solution then as I can see it is to make a case for every possible combination of the enum values ?

Something like

    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...

But that really isnt very desired (as it will quickly grow very big)

Right now i have 3 If conditions right after eachother instead

Something like

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

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

....

But that also means that if i have an enum with 20 values it have to go through 20 If conditions every single time instead of "jumping" to only the needed "case"/'s as when using a switch.

Is there some magic solution to solve this problem?

I have thought of the possibility to loop through the declared values and then use the switch, then it would only hit the switch for each value declared, but I don't know how it will work and if it performance vice is a good idea (compared to a lot of if's) ?

Is there an easy way to loop through all the enum values declared ?

I can only come up with using ToString() and splitting by "," and then loop through the array and parse every single string.


UPDATE:

I see that i haven't done a good enough job explaining. My example is to simple (tried to simplify my scenario).

I use it for a ActionMethodSelectorAttribute in Asp.net MVC to determine if a method should be available when resolving the url/route.

I do it by declaring something like this on the method

[ActionSelectorKeyCondition(CheckType.Form | CheckType.TempData, "SomeKey")]
public ActionResult Index()
{
    return View();
} 

That would mean that it should check if the Form or TempData have a key as specified for the method to be available.

The methods it will be calling (doSomething(), doSomethingElse() and doWhatever() in my previous example) will actually have bool as return value and will be called with a parameter (different collections that doesn't share a interface that can be used - see my example code in the link below etc).

To hopefully give a better idea of what i am doing i have pasted a simple example of what i am actually doing on pastebin - it can be found here http://pastebin.com/m478cc2b8

解决方案

How about this. Of course the arguments and return types of DoSomething, etc., can be anything you like.

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;
                }
            }
        }
    }
}

这篇关于打开枚举(带Flags属性),而不声明每一个可能的组合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆