C#中枚举成员的并集

本文关键字:枚举成员 | 更新日期: 2023-09-27 17:58:27

假设,我有一个enum BasicType,其定义如下:

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

BasicType标识执行任何Object的三元分类。随后,我意识到对象AB需要以与C类似的方式进行处理,因此我定义了另一个enum ObjectGroupType如下:

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

有了新的enum,我可以将几种已知类型的对象作为一个对象进行bucket处理。所以,当我接收到各种类型的对象流时,我实际上确定了它们是属于AB类型还是C类型。有没有一个优雅的解决方法?例如,我是否能够为ObjectGroupType中的A和B分配相同的枚举值?:

编辑1:我在这里找不到与问题相似的地方

编辑2:感谢Maurice的建设性意见——根据你的回答,我提出了这个重新定义的ObjectGroupType

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

这个有效吗?

本质上,当我处理AB类型的对象流时,我想确定类型a或类型B的对象。这与分层的两级决策树非常相似:

    object
    /     '
 AB        C
 /'
A  B

C#中枚举成员的并集

如果我误解了你的意图,我提前道歉,但听起来你几乎想允许基于枚举值在代码中处理多个不同的枚举类型。好的方面是,您已经可以使用逐位操作和枚举来做到这一点。

给定一个看起来像这样的枚举:

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

您可以设置一个比较值,它是几个值的按位OR:

var allowedValues = ObjectType.A | ObjectType.C;

这之所以有效,是因为枚举中的值的作用类似于封面下的位字段。

运行代码时,对allowedValues变量和测试变量进行逐位AND运算,看看它是否与测试变量匹配。如果是这样,那么它就是您想要的值之一:

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

下面是一个使用上面枚举的工作示例,它向您展示了它的工作原理。

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

祝你好运!

编辑:

我发现莫里斯·里夫斯的答案很好,我只想带来更多信息:

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

通过使用[Flags]属性,您可以创建枚举项的集合,这可以帮助您为每个集合建立不同的业务规则。

为了检查和项目是否存在于一个集合中,您可以执行以下操作:

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

如果你想在飞行中创建一组新的项目,你可以做:

var newGroup=ObjectType.A | ObjectType.BorCorD;

如果你想将一些业务规则应用于一个集合,除了一个项目,你可以这样做:

var newGroupExceptC =newGroup^=ObjectType.C;

现在,如果你检查元素C是否存在于集合中,你会得到false:

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

更多信息,您可以在这里找到

您可以使用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); });
    }
}

这种方法的缺点是失去了对象类型的强类型,即您可以分配任何值,而不仅仅是您在ObjectType中定义的值。