简体   繁体   English

C#中的枚举成员联盟

[英]Union of enum members in C#

Let us say, I have an enum BasicType , which is defined as follows: 让我们说,我有一个enum BasicType ,其定义如下:

    public enum ObjectType{
        A = 1,
        B = 2,
        C = 3,
    }

The BasicType identifies performs a ternary classification of any Object . BasicType标识对任何Object执行三元分类。 Subsequently, I realized that the objects A and B need to be treated in a similar way as compared to C , so I defined another enum ObjectGroupType as follows : 随后,我意识到对象A和对象B的处理方式与对象C相似,因此我定义了另一个enum ObjectGroupType ,如下所示:

public enum ObjectGroupType
{
   AB = 1,
   C = 2,
}

With the new enum, I am able to bucket objects of several known types as one. 使用新的枚举,我可以将几种已知类型的对象作为一个存储桶。 So, when I receive a stream of objects in various types, I actually identify whether they belong to AB or C type. 因此,当我收到各种类型的对象流时,实际上会确定它们是属于AB类型还是属于C类型。 Is there an elegant workaround for this? 是否有一个优雅的解决方法? For instance, will I be able to assign the same enum values for A and B in the ObjectGroupType ?: 例如,是否可以在ObjectGroupType为A和B分配相同的枚举值?

Edit 1 : I am unable to find the resemblance to the question here 编辑1 :我无法在此处找到与问题的相似之处

Edit 2 : Thank you Maurice for your constructive inputs -- taking cues from your answer, I came up with this redefined ObjectGroupType . 编辑2 :谢谢Maurice的建设性投入-借鉴您的回答,我提出了这个重新定义的ObjectGroupType

 public enum ObjectGroupType
 {
    AB = ObjectType.A | ObjectType.B
    C = 2,
 }

Is this valid? 这有效吗?

Essentially, when I process a stream of objects of type AB, I want to ascertain Type A or Type B objects. 本质上,当我处理AB类型的对象流时,我想确定Type A或Type B对象。 This is quite similar to a hierarchical two-level decision tree: 这与分层两级决策树非常相似:

    object
    /     \
 AB        C
 /\
A  B

I apologize in advance if I misread your intent, but it almost sounds like you want to allow multiple different enum types to be acted on in your code based on the enum value. 如果我误读了您的意图,我会向您道歉,但这听起来像是您想允许基于枚举值在代码中作用多种不同的枚举类型。 The good thing is that you can do that already with bitwise operations and enums. 好消息是,您可以使用按位运算和枚举来完成此操作。

Given an enum that looks like this: 给定一个如下所示的枚举:

[Flags]
enum ObjectType
{
    A = 1,
    B = 2,
    C = 4,
    D = 8
}

You can set a comparison value that is the bitwise OR of several values: 您可以设置一个比较值,它是多个值的按位或:

var allowedValues = ObjectType.A | ObjectType.C;

This works because the values in the enum act like bit fields under the covers. 之所以可行,是因为枚举中的值的作用就像是幕后的位字段。

When you run your code, you do a bitwise AND on the allowedValues variable and the test variable and see if it matches your test variable. 运行代码时,您对allowedValues变量和测试变量进行按位“与”运算,并查看其是否与测试变量匹配。 If it does, then it is one of the values you want: 如果是这样,则它是您想要的值之一:

if ((test & allowed) == test) ...

Below is a working example using the enum above that shows you how it works. 下面是一个使用上面的枚举的工作示例,向您展示了它的工作原理。

void Main()
{
    var allowed = ObjectType.A | ObjectType.C;

    var values = new int [] { 1, 2, 4, 8 };

    foreach (var i in values)
    {
        var test = (ObjectType)i;

        if ((test & allowed) == test)
        {
            Console.WriteLine("Found a match: {0}", test);
        }
        else
        {
            Console.WriteLine("No match: {0}", test);
        }
    }
}

Best of luck! 祝你好运!

You might use a int instead of an enum, use values that don't overlap when combined (ie values whose binary representation has only one bit on) and then perform a mask operation on the ObjectType of a parameter to determine if it is AB: 您可以使用int而不是enum,使用组合时不重叠的值(即,其二进制表示形式仅具有一位的值),然后对参数的ObjectType执行掩码操作以确定其是否为AB:

class SomeClass
{
    public static class ObjectType
    {
        public const int A = 1;
        public const int B = 2;
        public const int C = 4;
        public const int D = 8;
    }

    public int MyType;
    public string Title;
    static void Main(string[] args)
    {
        List<SomeClass> list = new List<SomeClass>()
        {
            new SomeClass() {Title ="I am of type A", MyType = ObjectType.A }
            ,new SomeClass() {Title ="I am of type B", MyType = ObjectType.B }
            ,new SomeClass() {Title ="I am of type AB", MyType = ObjectType.A | ObjectType.B }
        };

        list.ForEach(p => { if (p.MyType == (ObjectType.A | ObjectType.B)) Console.WriteLine(p.Title); });
    }
}

The downside of this approach is losing strong-typing of Object Type, ie you can assign any value not just those you define in the ObjectType. 这种方法的缺点是失去了对象类型的强大功能,即您可以分配任何值,而不仅仅是在ObjectType中定义的值。

Edit: 编辑:

I found the answer of Maurice Reeves very good, I only want to bring some more info: 我发现莫里斯·里夫斯的答案非常好,我只想带来一些更多信息:

   [Flags]
    public enum ObjectType
{
    None=0,
    A = 1,
    B = 2,
    C = 4,
    D = 8,
    E = 16,
    AorB=A|B,
    BorCorD=B|C|D,

}

By using [Flags] attribute, you can create sets of enum items, which can help you establishing different business rules for each set. 通过使用[Flags]属性,您可以创建枚举项目集,这可以帮助您为每个集合建立不同的业务规则。

In order to check if and item exist in a set you can do as follow: 为了检查集合中是否存在和项目,您可以执行以下操作:

public static bool IsAorB(this ObjectType item)
{
      return ObjectType.AorB.HasFlag(item);
}

if you want to creat on the fly new set of items, you can do: 如果您想即时创建新的项目集,则可以执行以下操作:

var newGroup=ObjectType.A | ObjectType.BorCorD;

if you want to apply some business rule to a set, except an item, you can do: 如果要对某个项目(项目除外)应用某些业务规则,则可以执行以下操作:

var newGroupExceptC =newGroup^=ObjectType.C;

Now if you check if element C exist in the set you will get false: 现在,如果您检查元素C是否存在于集合中,您将得到false:

bool exist=newGroupExceptC.HasFlag(ObjectType.C) // =false

more info you can find here 您可以在这里找到更多信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM