共用方式為


資料合約中的列舉型別

列舉可以在資料合約模型中表示。本主題將逐步介紹幾個範例,說明程式設計模型。

列舉基本知識

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

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

<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 
[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
}

只有 condition 欄位設定為值 NewUsedRental 的其中之一時,才可以傳送或接收 Car 類別的執行個體。如果 conditionBrokenStolen,便會擲回 SerializationException

您可以和往常一樣,對列舉資料合約使用 DataContractAttribute 屬性 (NameNamespace)。

列舉成員值

資料合約通常包括列舉成員名稱,而不是數值。然而,當使用資料合約模型時,如果接收端是 WCF 用戶端,匯出的結構描述就會保存數值。請注意,當使用 使用 XmlSerializer 類別時則否。

在前例中,如果 condition 設定為 Used 且資料序列化為 XML,結果 XML 就是 <condition>Used</condition> 而不是 <condition>1</condition>。因此,下列資料合約相等於 CarConditionEnum 的資料合約。

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

例如,您可以在傳送端上使用 CarConditionEnum,而在接收端上使用 CarConditionWithNumbers。雖然傳送端對 Used 使用 "1" 值,而接收端使用 "20" 值,但是 XML 表示法對兩端都是 <condition>Used</condition>

如果要包含在資料合約中,您必須套用 EnumMemberAttribute 屬性。在 .NET Framework 中,您永遠可以對列舉套用特殊值 0 (零),這也是任何列舉的預設值。然而,即使這個特殊的零值也無法序列化,除非它標上 EnumMemberAttribute 屬性。

這種情形有兩個例外狀況:

  • 旗標列舉 (本主題稍後說明)。

  • EmitDefaultValue 屬性設定為 false 的列舉資料成員 (在這種情況中,只會從序列化的資料中省略值為零的列舉)。

自訂列舉成員值

您可以使用 EnumMemberAttribute 屬性 (Attribute) 的 Value 屬性 (Property) 來自訂列舉成員值,該值會成為資料合約的一部分。

例如,下列資料合約也相等於 CarConditionEnum 的資料合約。

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

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

簡單列舉

您也可以序列化列舉型別至尚未套用的 DataContractAttribute 屬性。此類列舉型別的處理方式完全如先前所述,除了每個成員 (未套用 NonSerializedAttribute 屬性) 會被視為已套用 EnumMemberAttribute 屬性之外。例如,以下列舉隱含具有相等於上一個 CarConditionEnum 範例的資料合約。

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

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

簡單列舉的注意事項

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

SerializableAttribute 屬性是否套用至列舉並沒有差別。

事實上 DataContractSerializer 類別允許套用至列舉成員的 NonSerializedAttribute 屬性,與 BinaryFormatterSoapFormatter 的行為是不同的。這兩個序列化程式都會略過 NonSerializedAttribute 屬性。

旗標列舉

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

如果要執行這項操作,請將 DataContractAttribute 屬性套用至旗標列舉,然後將所有為二之次方的成員以 EnumMemberAttribute 屬性標示。請注意,如果要使用旗標列舉,級數必須是 2 的次方的不中斷序列 (例如,1、2、4、8、16、32、64)。

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

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

  2. 請嘗試將數值中斷至某個總和,以具有對應至該總和之各部分的列舉成員 (每個都套用 EnumMemberAttribute 屬性)。傳送所有這些成員的清單。請注意,「窮盡演算法」(Greedy Algorithm) 是用於尋找此類總和,因此即使此類總和存在,也不保證會找到。如果要避免這個問題,請確保列舉成員的數值是二的次方。

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

範例

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

<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 
[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
}

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

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.
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

另請參閱

參考

DataContractSerializer

概念

使用資料合約
指定服務合約中的資料傳輸