C# 枚舉的flags 標誌位應用

枚舉有個特性叫標誌位,使用方法如下

[Flags]
enum Foo
{
    a =1,
    b = 2, 
    c = 4, 
    d = 8
}

每個值需要爲2的n次方,保證多個值的組合不會重複.

這樣在判斷其中一個枚舉值c 是否在a,b,c這個範圍中就可以簡化寫法

常規寫法如下

var c = Foo.c;
if( c == Foo.a || c == Foo.b || c == Foo.c )
{

}

因爲值爲2的n次方,所以可以通過按位相與來得出是否在範圍內

var c = Foo.c;
if( (c & ( Foo.a | Foo.b | Foo.c ) != c )
{

}

注意,如果c在範圍內則結果等於c,否則結果爲0

 

可以寫個擴展方法

    public static class  EnumExtension
    {
        /// <summary>
        /// 判斷該枚舉是否在範圍內  注意:該枚舉類型需要有[Flags] 標註
        /// </summary>
        /// <param name="source">待比較的值</param>
        /// <param name="range">枚舉範圍</param>
        /// <returns></returns>
        public static bool IsIn(this Enum source, params Enum[] range)
        {
            if(range.Length == 0)
            {
                return false;
            }
            else if(range.Length == 1)
            {
                return source == range[0];
            }
            int r = Convert.ToInt32(range[0]);
            for (int i = 1; i < range.Length; i++)
            {
                r |= Convert.ToInt32(range[i]);
            }
            return !((Convert.ToInt32(source) & r) == 0);
        }
    }

 

調用如下

var c = Foo.c;
if(c.IsIn(Foo.a, Foo.b, Foo.c))
{
}

 

此外flags還會重寫該枚舉的ToString()

比如  由於3 = 1 | 2,所以3就相當於a|b

當對3強轉爲Foo後進行ToString會輸出 a,b 而不是3

 

 這樣簡單組合就可以得到新的有效枚舉值,這種設計在權限等方面應用很多.

比如linux的文件權限 read write execute,縮寫爲r w x,對應值爲 4 2 1

當需要一個值爲

可讀可寫,    r w, 4 | 2 = 6

可寫可執行, w x, 2 | 1 = 3

可讀可執行,  r x,  4 | 1 = 5

可讀可寫可執行 r w x, 4 | 2 | 1 = 7

 

當然,也可以加上命名指定枚舉值組合,比如定義一個ac 來替代a|c

[Flags]
enum Foo
{
    a = 1,
    b = 2,
    c = 4,
    ac = a | c,
    d = 8
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章