解枚舉的FlagsAttribute之惑

本文轉自:http://hi.baidu.com/%D6%AA%D0%D0%BA%CF%C8%FD/blog/item/1db39b3ec8ada93a71cf6c35.html 

FlagsAttribute類:指示可以將枚舉作爲位域(即一組標誌)處理。
只有要對數值執行按位運算(AND、OR、XOR)時纔對枚舉使用 FlagsAttribute 自定義屬性。

// Example of the FlagsAttribute attribute.
using System;

class FlagsAttributeDemo
{
// Define an Enum without FlagsAttribute.
enum SingleHue : short
{
Black = 0,
Red = 1,
Green = 2,
Blue = 4
};

// Define an Enum with FlagsAttribute.
[FlagsAttribute]
enum MultiHue : short
{
Black = 0,
Red = 1,
Green = 2,
Blue = 4
};

static void Main( )
{
Console.WriteLine(
"This example of the FlagsAttribute attribute \n" +
"generates the following output." );
Console.WriteLine(
"\nAll possible combinations of values of an \n" +
"Enum without FlagsAttribute:\n" );

// Display all possible combinations of values.
for( int val = 0; val <= 8; val++ )
Console.WriteLine( "{0,3} - {1}",
val, ( (SingleHue)val ).ToString( ) );

Console.WriteLine(
"\nAll possible combinations of values of an \n" +
"Enum with FlagsAttribute:\n" );

// Display all possible combinations of values.
// Also display an invalid value.
for( int val = 0; val <= 8; val++ )
Console.WriteLine( "{0,3} - {1}",
val, ( (MultiHue)val ).ToString( ) );
}
}

/*
This example of the FlagsAttribute attribute
generates the following output.

All possible combinations of values of an
Enum without FlagsAttribute:

0 - Black
1 - Red
2 - Green
3 - 3
4 - Blue
5 - 5
6 - 6
7 - 7
8 - 8

All possible combinations of values of an
Enum with FlagsAttribute:

0 - Black
1 - Red
2 - Green
3 - Red, Green
4 - Blue
5 - Red, Blue
6 - Green, Blue
7 - Red, Green, Blue
8 - 8
*/

===========================分隔符========================
枚舉類型可是用Flags 標誌,表示這些枚舉類型可以作爲位域(即一組標誌)處理。

比如下面的枚舉類型:
    [Flags]
    enum MultiHue : short
    {
        Black = 0,
        Red = 1,
        Green = 2,
        Blue = 4
    };

這裏用 2 的冪(即 1、2、4、8 等)定義枚舉常量。這意味着組合的枚舉常量中的各個標誌都不重疊。

但是,要注意的是:在當前程序中,如果你沒有定義這些枚舉類型的值,則默認系統給你的定義可不是 2 的冪,而是從0開始,每次累加1。

比如下面的代碼:
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(MultiHue.Blue);
            Console.WriteLine((int)MultiHue.Blue);
            Console.ReadLine();
        }
    }

    [Flags]
    enum MultiHue : short
    {
        Black,
        Red,
        Green,
        Blue
    }
控制檯打印出來的是 :

Blue
3

所以,到目前的結論是:在定義會位操做的枚舉類型的時候,必須用 2 的冪(即 1、2、4、8 等)定義枚舉常量。不可以不附值。

而如果你的這個枚舉類型被 Web Service 作爲一個方法的參數使用了。
在客戶端VS2005 系統自動會給你的MultiHue 附值。
客戶端會產生了下面的代碼,而不管你服務器端定義的枚舉數字值是多少。:

    [System.FlagsAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "2.0.50727.42")]
    [System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/")]
    public enum MultiHue
    {
        Black = 1,
        Red = 2,
        Green = 4,
        Blue = 8
    };

注意,不論我們服務器段是否給 ,每個枚舉類型附值,客戶端VS2005替你產生的代碼都是上述方式。
這時候你會發現,每個枚舉類型的數字值可能會發生變化了。

原因就是 枚舉類型的序列化是序列化成了文本,而不是數字。
由於客戶端和服務器端沒有數字的傳遞,當然客戶端和服務器端的枚舉項的值當然有很大的可能會不一樣了。
所以這裏的結論是:如果Web Service用到枚舉類型,一定不要用枚舉類型的數字值,因爲服務器端和客戶端會不一樣。
參考:http://ikriv.com:8765/en/prog/info/dotnet/WebServices_and_Enums.html

綜上所述。

如果你希望對枚舉類型進行位操作,

比如注意以下兩點:
1、在定義的時候,必須用 2 的冪(即 1、2、4、8 等)定義枚舉常量。不可以不附值。
2、如果Web Service用到枚舉類型,一定不要用枚舉類型的數字值,因爲服務器端和客戶端會不一樣。

再看一個稍稍複雜的例子,用上面的知識點,就可以解釋後面的例子爲啥會這樣。

比如有這樣一個Web Service。
[Flags]
public enum MultiHue
{
    Black = 8,
    Red = 1,
    Green = 2,
    Blue = 4
};
    [WebMethod]
    public MultiHue GetColor()
    {
        return MultiHue.Red | MultiHue.Green | MultiHue.Black;
    }
客戶端調用代碼如下:
            localhost.WebService ws = new Client.localhost.WebService();
            localhost.MultiHue re = ws.GetColor();
            Console.WriteLine(re);
            Console.WriteLine((int)re);
            Console.ReadLine();
這時候控制檯顯示的信息是:
Black, Red, Green
7
而這時候VS2005產生的客戶端的MultiHue 枚舉爲:
    [System.FlagsAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "2.0.50727.42")]
    [System.SerializableAttribute()]
    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/")]
    public enum MultiHue {
        /// <remarks/>
        Black = 1,
        /// <remarks/>
        Red = 2,
        /// <remarks/>
        Green = 4,
        /// <remarks/>
        Blue = 8,
    }
用我們前面提到的兩個知識點,就可以解釋爲何會這樣。

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