使用Flags扩展枚举,会干扰当前的使用

时间:2011-11-02 16:51:01

标签: c# enums

系统有这样一个简单的枚举,

public enum SomeEnum : short
{ 
    Ok = 0,
    Missing = 17,
};

现在这个枚举现在需要在不改变现有枚举值的外观的情况下将更多信息掩盖到其中。枚举将获得一些新值,

[Flags]
public enum SomeEnum : short
{ 
    Ok = 0,
    Missing = 17,
    Blocking = 18, // Values could be anything
    Low  = 19,     // Values could be anything
};

我担心当前的枚举使用会出现问题。看来我是对的,但是我希望我的帮助被证明是错误的。直到今天的使用是围绕SomeEnum.Ok构建的。明天也好,但是需要额外的信息。我需要屏蔽枚举值而不影响它的当前行为,这可能来自任何公共引用;

someEnumVariable.ToString()
(int)someEnumVariable
someVar = SomeEnum.Ok
Enum.Parse(typeOf(SomeEnum), someString)

如果我用

标记枚举

var test = (SomeEnum.Ok | SomeEnum.Blocking);
两个标志都可以建立,即test.HasFlags(SomeEnum.Ok)test.HasFlags(SomeEnum.Blocking),但枚举表示为SomeEnum.Blocking,这是不可能的。

有什么想法吗?

3 个答案:

答案 0 :(得分:2)

http://msdn.microsoft.com/en-us/library/system.flagsattribute.aspx

我认为快速介绍二进制OR是有序的。

|不只是让你将两个整数潜入一个变量。它执行数学运算。

因此,除0以外的任何值与0一起使用将返回该值本身。

如果提供的标志值不是单个位,则可能会遇到进一步的意外行为,例如1,2,4,8,16。

修改

如果要围绕现有值构建Flags枚举,则可以执行此操作。不要将当前保留的位10001(17)用于任何其他值,并且在测试Ok时要小心。

答案 1 :(得分:2)

由于SomeEnum.OK的值为0,因此调用HasFlag(SomeEnum.OK)始终返回true。当您将枚举屏蔽在一起时,该过程依赖于以下事实:任何枚举值组合的总和将是唯一的。通常情况下,您可以使用2^02^12^2等值开始设置这些值。例如:

[Flags]
public enum SomeEnum : short
{ 
    Ok = 1,
    Missing = 2,
    Blocking = 4, // Values could be anything
    Low  = 8,     // Values could be anything
}

如果要一起屏蔽这些值,则必须使用Flags属性。如果您无法重构并更改SomeEnum.OK的值,则可能需要依赖传递SomeEnum[],而不是单个屏蔽的SomeEnum值。

修改
关于使用上面定义的枚举将值屏蔽在一起的快速说明。请使用以下代码:

var t1 = (int)(SomeEnum.OK | SomeEnum.Missing);       //t1 = 1 + 2 = 3
var t2 = (int)(SomeEnum.Missing | SomeEnum.Blocking); //t2 = 2 + 4 = 6
var t3 = (int)(SomeEnum.OK | SomeEnum.Low);           //t3 = 1 + 8 = 9
var t4 = (int)SomeEnum.OK;                            //t4 = 1
var s1 = (SomeEnum.Ok).ToString();                    //s1 = "Ok"
var s2 = (SomeEnum.Ok | SomeEnum.Missing).ToString(); //s2 = "Ok, Missing"

当这些项被“或”在一起时,.NET只会将这些值相加,以生成一个新的唯一值,该值表示OR项的组合。使用2的幂的枚举值可确保组合始终是唯一的。

答案 2 :(得分:0)

以下是如何使用bitflag完成此操作的示例。但是,这可能会迫使您更改现有的旗帜比较。

 [FlagsAttribute] 
enum tester
{
    alpha = 1,
    beta = 2,
    gamma = 4,
    reggy=3
}

class Program
{
    static void Main(string[] args)
    {
        tester t = tester.alpha | tester.beta;
        if (t == tester.alpha)
            Console.WriteLine("alpha only");
        if ((t & tester.alpha) != 0)
            Console.WriteLine("alpha");
        if ((t & tester.beta) != 0)
            Console.WriteLine("beta");
        if ((t & tester.gamma) != 0)
            Console.WriteLine("gamma");
        if (t == (tester.beta | tester.alpha))
            Console.WriteLine("alphabeta");

        //this will produce alpha, beta, alphabeta