FlagsAttribute Enum在C#中的行为是什么?

时间:2012-02-21 09:01:30

标签: c# .net enums

我有以下代码:

namespace ConsoleApplication1
{
    internal class Program
    {
        [FlagsAttribute]
        private enum RenderType
        {
            DataUri = 0,
            GZip = 1,
            ContentPage = 2,
            ViewPage = 4,
            HomePage = 8
        }

        private static void Main()
        {

            // 4.
            // Set a new enum in three statements.
            RenderType type2 = RenderType.ViewPage;
            // 5.
            // See if the enum contains this flag.
            if ((type2 & RenderType.ViewPage) == RenderType.ViewPage)
            {
                Console.WriteLine("ViewPage");
            }

            if ((type2 & RenderType.DataUri) == RenderType.DataUri)
            {
                Console.WriteLine("DataUri");
            }
            if ((type2 & RenderType.GZip) == RenderType.GZip)
            {
                Console.WriteLine("GZip");
            }

        }
    }

}

每当我运行此代码时,它都会给出一个输出:

的ViewPage DataUri

我想要输出只是ViewPage,因为我将值赋给我的枚举ViewPage。

有人可以帮我吗?为什么是这样?我的Enum声明或代码有什么问题吗?

7 个答案:

答案 0 :(得分:4)

您已声明DataUri = 0所以

(type2 & RenderType.DataUri) == RenderType.DataUri

将始终评估为true

在1开始有效的枚举值。

答案 1 :(得分:1)

任何以零为单位的数字都为零。用一个开始枚举,用两个幂增加。此外,更好地了解binary numbersbitwise operators将有助于

答案 2 :(得分:1)

DataUri为0:所以x & DataUri始终为零! 试试这个:

if(type2 != RenderType.DataUri) {  
    if ((type2 & RenderType.ViewPage) == RenderType.ViewPage)
    {
        Console.WriteLine("ViewPage");
    }


    if ((type2 & RenderType.GZip) == RenderType.GZip)
    {
        Console.WriteLine("GZip");
    }
}

使用Bitmasks时,值0通常表示NONE-Flag。所以你应该从1到2 ^ n开始计数,这是一个更好的做法恕我直言:

    [FlagsAttribute]
    private enum RenderType
    {
        None = 0,
        DataUri = 1,
        GZip = 2,
        ContentPage = 4,
        ViewPage = 8,
        HomePage = 16
    }

答案 3 :(得分:0)

因为x & 0总是等于零。

答案 4 :(得分:0)

不要将0(零)指定为[Flags]枚举的可能值。请记住,[Flags]枚举是一个位字段,值为零并不真正映射到任何字段,因此它将始终返回true。

来自Krzysztof Cwalina的Framework Design Guidelines

Avoid using flag enum values normal members that are negative or zero. 
     

负值会在按位运算中产生意外/混乱的结果。枚举值为零会产生问题和操作等:

答案 5 :(得分:0)

原因是RenderType.DataUri的值为0

您的代码所做的是通过在type2和它正在测试的枚举成员之间执行按位and操作来检查type2枚举变量的按位配置。

在您的示例中,type2的值为4,二进制为0100(最多为枚举所需的4位)。当您测试RenderType.GZip0001)时,会执行以下计算:

0100 & 0001 = 0000

0000 != 0001起,RenderType.GZip位未在type2中设置。但是,0100 & 0000始终为0000,因此在检查RenderType.DataUri时您始终会成真。

本质上,Flags枚举对每个成员使用不同的位,但由于0不表示整数中的位,因此它不会按预期运行。

答案 6 :(得分:0)

正如其他人所说,由于二元算法的工作原理,你应该在1开始使用Flags枚举。我只想补充一点,你可能想要使用HasFlag方法(我相信.NET 4.0中的新方法)来检查标志:

if(type2.HasFlag(RenderType.ViewPage))
{
   ...
}

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