FlagsAttribute枚举在C#中的行为是什么

本文关键字:是什么 枚举 FlagsAttribute | 更新日期: 2023-09-27 18:25:20

我有以下代码:

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

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

查看页面DataUri

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

有人能帮我吗?为什么会这样?我的枚举声明或代码有什么问题吗?

FlagsAttribute枚举在C#中的行为是什么

您已经声明DataUri = 0所以

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

将始终评估为CCD_ 2。

从1开始您的有效枚举值。

任何按位加零的数字都是零。以1开始枚举,然后增加2的幂。此外,更好地理解二进制数和逐位运算符将有助于

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

使用位掩码时,值0通常表示NONE标志。所以你应该从1开始计数到2^n,这是一个更好的练习IMHO:

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

因为x & 0总是等于零。

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

根据Krzysztof Cwalina的框架设计指南:

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

负值会在按位操作中产生意外/令人困惑的结果。枚举值为零会给和操作等带来问题:

原因是RenderType.DataUri的值为0

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

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

0100 & 0001 = 0000

由于0000 != 0001,所以在type2中不设置RenderType.GZip比特。但是,0100 & 0000始终是0000,所以在检查RenderType.DataUri时,您总是会得到true。

本质上,true0枚举为其每个成员使用不同的位,但由于0不表示整数中的位,因此它的行为不会像预期的那样。

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

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

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