共用方式為


數據合約中的列舉型別

枚舉可以在資料契約模型中表示。 本主題會逐步解說數個說明程序設計模型的範例。

列舉基本概念

在數據合約模型中使用列舉型別的其中一種方法是將 DataContractAttribute 屬性套用至型別。 然後,您必須將 EnumMemberAttribute 屬性套用至數據合約中必須包含的每個成員。

下列範例顯示兩個類別。 第一個使用列舉,第二個定義列舉。

[DataContract]
public class Car
{
    [DataMember]
    public string model;
    [DataMember]
    public CarConditionEnum condition;
}

[DataContract(Name = "CarCondition")]
public enum CarConditionEnum
{
    [EnumMember]
    New,
    [EnumMember]
    Used,
    [EnumMember]
    Rental,
    Broken,
    Stolen
}
<DataContract()> _
Public Class Car
    <DataMember()> _
    Public model As String
    <DataMember()> _
    Public condition As CarConditionEnum
End Class

<DataContract(Name:="CarCondition")> _
Public Enum CarConditionEnum
    <EnumMember> NewCar
    <EnumMember> Used
    <EnumMember> Rental
    Broken
    Stolen
End Enum

只有在Car欄位設定為conditionNewUsed其中一個值時,才可以傳送或接收Rental類別的實例。 若conditionBrokenStolen,則會拋出SerializationException

您可以像往常一樣使用 DataContractAttribute 屬性 (NameNamespace) 來列舉數據合約。

列舉成員值

一般而言,數據合約包含列舉成員名稱,而非數值。 不過,使用數據合約模型時,如果接收端是WCF用戶端,則導出的架構會保留數值。 請注意,使用 XmlSerializer 類別 時,情況並非如此。

在上述範例中,如果 condition 設定為 Used ,且數據串行化為 XML,則產生的 XML 為 <condition>Used</condition> ,而不是 <condition>1</condition>。 因此,下列數據合約相當於 的數據合約 CarConditionEnum

[DataContract(Name = "CarCondition")]
public enum CarConditionWithNumbers
{
    [EnumMember]
    New = 10,
    [EnumMember]
    Used = 20,
    [EnumMember]
    Rental = 30,
}
<DataContract(Name:="CarCondition")> _
Public Enum CarConditionWithNumbers
    <EnumMember> NewCar = 10
    <EnumMember> Used = 20
    <EnumMember> Rental = 30
End Enum

例如,您可以在傳送端使用CarConditionEnum,在接收端使用CarConditionWithNumbers。 雖然傳送端使用值「1」,接收端使用值「20」,但 XML 表示在兩端均為 Used

若要包含在資料合約中,您必須套用 EnumMemberAttribute 屬性。 在 .NET Framework 中,您一律可以將特殊值 0 (零) 套用至列舉,這也是任何列舉的預設值。 不過,即使這個特殊的零值也無法串行化,除非它以 EnumMemberAttribute 屬性標示。

有兩個例外狀況:

  • 旗標列舉 (本主題稍後討論)。

  • 列舉數據成員,其屬性設為 EmitDefaultValue 且其值為 false 時,擁有值為零的列舉將不會包含在序列化數據中。

自定義列舉成員值

您可以使用 Value 屬性中的 EnumMemberAttribute 屬性,自定義作為數據合約一部分的列舉成員值。

例如,下列數據合約也相當於CarConditionEnum的數據合約。

[DataContract(Name = "CarCondition")]
public enum CarConditionWithDifferentNames
{
    [EnumMember(Value = "New")]
    BrandNew,
    [EnumMember(Value = "Used")]
    PreviouslyOwned,
    [EnumMember]
    Rental
}
<DataContract(Name:="CarCondition")> _
Public Enum CarConditionWithDifferentNames
    <EnumMember(Value:="New")> BrandNew
    <EnumMember(Value:="Used")> PreviouslyOwned
    <EnumMember> Rental
End Enum

序列化時,的值 PreviouslyOwned 具有 XML 表示法 <condition>Used</condition>

簡單列舉

您也可以序列化尚未套用DataContractAttribute屬性的列舉型別。 這類列舉型別的處理方式與先前所述完全相同,不同在於每個成員(未套用 NonSerializedAttribute 屬性的成員)將被視為已套用 EnumMemberAttribute 屬性。 例如,下列列舉會隱含地具有相當於上述 CarConditionEnum 範例的數據合約。

public enum CarCondition
{
    New,
    Used,
    Rental,
    [NonSerialized]
    Lost
}
Public Enum CarCondition
    [New]
    Used
    Rental
End Enum

當您不需要自定義列舉的數據合約名稱和命名空間和列舉成員值時,可以使用簡單的列舉。

簡單列舉的注意事項

EnumMemberAttribute 屬性套用至簡單列舉沒有任何作用。

不論屬性是否 SerializableAttribute 套用至 列舉,都沒有任何差異。

DataContractSerializer 類別接受套用到列舉成員的 NonSerializedAttribute 屬性,這與 BinaryFormatterSoapFormatter 的行為不同。 這兩個串行化程序都會忽略 NonSerializedAttribute 屬性。

旗標列舉

您可以將 FlagsAttribute 屬性套用至列舉類型。 在此情況下,可以同時傳送或接收零個或多個列舉值的清單。

若要這樣做,請將 DataContractAttribute 屬性套用至旗標列舉,然後使用 EnumMemberAttribute 屬性標記所有是二的冪次方的成員。 請注意,若要使用旗標列舉,進展必須是 2 的不間斷權力序列(例如 1、2、4、8、16、32、64)。

下列步驟適用於旗標的列舉值之傳送:

  1. 嘗試尋找套用 EnumMemberAttribute 屬性的列舉成員,以對應至該數值。 如果找到,請傳送只包含該成員的清單。

  2. 嘗試將數值分成總和,使列舉成員(每一個成員都套用EnumMemberAttribute屬性)對應到總和的每一部分。 傳送所有這些成員的清單。 請注意,貪婪演算法 是用來尋找這類總和的,因此即使這樣的總和存在,也不能保證一定能找到。 若要避免這個問題,請確定列舉成員的數值是兩個的乘冪。

  3. 如果上述兩個步驟失敗,且數值為非零值,則擲回 SerializationException。 如果數值為零,請傳送空白清單。

範例

下列列舉範例可用於旗標作業。

[DataContract][Flags]
public enum CarFeatures
{
    None = 0,
    [EnumMember]
    AirConditioner = 1,
    [EnumMember]
    AutomaticTransmission = 2,
    [EnumMember]
    PowerDoors = 4,
    AlloyWheels = 8,
    DeluxePackage = AirConditioner | AutomaticTransmission | PowerDoors | AlloyWheels,
    [EnumMember]
    CDPlayer = 16,
    [EnumMember]
    TapePlayer = 32,
    MusicPackage = CDPlayer | TapePlayer,
    [EnumMember]
    Everything = DeluxePackage | MusicPackage
}
<DataContract(), Flags()> _
Public Enum CarFeatures
    None = 0
    <EnumMember> AirConditioner = 1
    <EnumMember> AutomaticTransmission = 2
    <EnumMember> PowerDoors = 4
    AlloyWheels = 8
    DeluxePackage = AirConditioner Or AutomaticTransmission Or PowerDoors Or AlloyWheels
    <EnumMember> CDPlayer = 16
    <EnumMember> TapePlayer = 32
    MusicPackage = CDPlayer Or TapePlayer
    <EnumMember> Everything = DeluxePackage Or MusicPackage
End Enum

下列範例值會依指示串行化。

CarFeatures cf1 = CarFeatures.AutomaticTransmission;
//Serialized as <cf1>AutomaticTransmission</cf1>

CarFeatures cf2 = (CarFeatures)5;
//Serialized as <cf2>AirConditioner PowerDoors</cf2> since 5=1+4

CarFeatures cf3 = CarFeatures.MusicPackage;
//Serialized as <cf3>CDPlayer TapePlayer</cf3> since MusicPackage itself is not an EnumMember

CarFeatures cf4 = CarFeatures.Everything;
//Serialized as <cf4>Everything</cf4> since Everything itself is an EnumMember

CarFeatures cf5 = CarFeatures.DeluxePackage;
//Throws a SerializationException since neither DeluxePackage nor AlloyWheels are EnumMembers

CarFeatures cf6 = CarFeatures.None;
//Serialized as the empty list <cf6></cf6> since there is no EnumMember mapped to zero
Private cf1 As CarFeatures = CarFeatures.AutomaticTransmission
'Serialized as <cf1>AutomaticTransmission</cf1>

Private cf2 As CarFeatures = ctype(5, CarFeatures)
'Serialized as <cf2>AirConditioner PowerDoors</cf2> since 5=1+4

Private cf3 As CarFeatures = CarFeatures.MusicPackage
'Serialized as <cf3>CDPlayer TapePlayer</cf3> since MusicPackage 
' itself is not an EnumMember.

Private cf4 As CarFeatures = CarFeatures.Everything
'Serialized as <cf4>Everything</cf4> since Everything itself is an EnumMember.

Private cf5 As CarFeatures = CarFeatures.DeluxePackage
'Throws a SerializationException since neither DeluxePackage nor 
' AlloyWheels are EnumMembers.

Private cf6 As CarFeatures = CarFeatures.None
'Serialized as the empty list <cf6></cf6> since there is no EnumMember mapped to zero.

另請參閱