Enumerationstypen in DatenverträgenEnumeration Types in Data Contracts

Enumerationen können im Datenvertragsmodell ausgedrückt werden.Enumerations can be expressed in the data contract model. In diesem Thema werden mehrere Beispiele behandelt, in denen das Programmiermodell erklärt wird.This topic walks through several examples that explain the programming model.

Grundlagen der EnumerationEnumeration Basics

Eine Möglichkeit, Enumerationstypen im Datenvertragmodell zu verwenden, besteht darin, das DataContractAttribute-Attribut auf den Typ anzuwenden.One way to use enumeration types in the data contract model is to apply the DataContractAttribute attribute to the type. Anschließend müssen Sie das EnumMemberAttribute-Attribut auf jeden Member anwenden, der im Datenvertrag enthalten sein soll.You must then apply the EnumMemberAttribute attribute to each member that must be included in the data contract.

Das folgende Beispiel zeigt zwei Klassen.The following example shows two classes. Die erste Klasse verwendet die Enumeration, und die zweite Klasse definiert die Enumeration.The first uses the enumeration and the second defines the enumeration.

[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 

Sie können eine Instanz der Car-Klasse nur senden oder empfangen, wenn das Feld condition auf einen der folgenden Werte festgelegt ist: New, Used oder Rental.An instance of the Car class can be sent or received only if the condition field is set to one of the values New, Used, or Rental. Wenn condition den Wert Broken oder Stolen hat, wird eine SerializationException ausgelöst.If the condition is Broken or Stolen, a SerializationException is thrown.

Sie können die DataContractAttribute-Eigenschaften (Name und Namespace) wie gewohnt für Enumerationsdatenverträge verwenden.You can use the DataContractAttribute properties (Name and Namespace) as usual for enumeration data contracts.

EnumerationsmemberwerteEnumeration Member Values

Im Allgemeinen enthält der Datenvertrag Enumerationsmembernamen, keine numerischen Werte.Generally the data contract includes enumeration member names, not numerical values. Allerdings behält das exportierte Schema, wenn das datenvertragsmodell verwenden, wenn der Empfängerseite wird genauso eine WCF-Client ist, die numerischen Werte.However, when using the data contract model, if the receiving side is a WCF client, the exported schema preserves the numerical values. Beachten Sie, dass dies nicht der Fall ist, bei Verwendung der verwenden der XmlSerializer-Klasse.Note that this is not the case when using the Using the XmlSerializer Class.

Wenn im obigen Beispiel condition auf Used festgelegt ist und die Daten in XML serialisiert werden, lautet das XML-Ergebnis <condition>Used</condition>``<condition>1</condition>, und nicht .In the preceding example, if condition is set to Used and the data is serialized to XML, the resulting XML is <condition>Used</condition> and not <condition>1</condition>. Deshalb entspricht der folgende Datenvertrag dem Datenvertrag von CarConditionEnum.Therefore, the following data contract is equivalent to the data contract of 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 

Sie können beispielsweise CarConditionEnum auf der Absenderseite und CarConditionWithNumbers auf der Empfängerseite verwenden.For example, you can use CarConditionEnum on the sending side and CarConditionWithNumbers on the receiving side. Obwohl die Absenderseite den Wert 1 und die Empfängerseite den Wert 20 für Used verwendet, lautet die XML-Darstellung für beide Seiten <condition>Used</condition>.Although the sending side uses the value "1" for Used and the receiving side uses the value "20," the XML representation is <condition>Used</condition> for both sides.

Um das Einbinden in den Datenvertrag zu erreichen, müssen Sie das EnumMemberAttribute-Attribut anwenden.To be included in the data contract, you must apply the EnumMemberAttribute attribute. Unter .NET Framework.NET Framework können Sie immer den Sonderwert 0 (Null) auf eine Enumeration anwenden. Dabei handelt es sich auch um den Standardwert für Enumerationen.In the .NET Framework.NET Framework, you can always apply the special value 0 (zero) to an enumeration, which is also the default value for any enumeration. Auch dieser Sonderwert 0 kann jedoch nur serialisiert werden, wenn er mithilfe des EnumMemberAttribute-Attributs gekennzeichnet ist.However, even this special zero value cannot be serialized unless it is marked with the EnumMemberAttribute attribute.

Dabei gelten zwei Ausnahmen:There are two exceptions to this:

  • Flagenumerationen (weiter unten in diesem Thema beschrieben).Flag enumerations (discussed later in this topic).

  • Enumerationsdatenmember, für die die EmitDefaultValue-Eigenschaft auf false festgelegt ist. (In diesem Fall wird die Enumeration mit dem Wert "0" einfach aus den serialisierten Daten weggelassen.)Enumeration data members with the EmitDefaultValue property set to false (in which case, the enumeration with the value zero is omitted from the serialized data).

Anpassen von EnumerationsmemberwertenCustomizing Enumeration Member Values

Sie können den Enumerationsmemberwert anpassen, der Teil des Datenvertrags ist, indem Sie die Value-Eigenschaft des EnumMemberAttribute-Attributs verwenden.You can customize the enumeration member value that forms a part of the data contract by using the Value property of the EnumMemberAttribute attribute.

Der folgende Datenvertrag entspricht auch dem Datenvertrag von CarConditionEnum.For example, the following data contract is also equivalent to the data contract of the 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 

Nach der Serialisierung weist der Wert von PreviouslyOwned die XML-Darstellung <condition>Used</condition> auf.When serialized, the value of PreviouslyOwned has the XML representation <condition>Used</condition>.

Einfache EnumerationenSimple Enumerations

Sie können auch Enumerationstypen serialisieren, auf die das DataContractAttribute-Attribut nicht angewendet wurde.You can also serialize enumeration types to which the DataContractAttribute attribute has not been applied. Enumerationstypen dieser Art werden exakt wie zuvor beschrieben behandelt. Es gilt jedoch die Ausnahme, dass jeder Member (auf den das NonSerializedAttribute-Attribut nicht angewendet wurde) so behandelt wird, als ob das EnumMemberAttribute-Attribut angewendet wurde.Such enumeration types are treated exactly as previously described, except that every member (that does not have the NonSerializedAttribute attribute applied) is treated as if the EnumMemberAttribute attribute has been applied. Zum Beispiel verfügt die folgende Enumeration implizit über einen Datenvertrag, der dem Datenvertrag im vorherigen CarConditionEnum-Beispiel entspricht.For example, the following enumeration implicitly has a data contract equivalent to the preceding CarConditionEnum example.

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

Sie können einfache Enumerationen verwenden, wenn es nicht erforderlich ist, den Datenvertragsnamen und den Namespace der Enumeration und die Enumerationsmemberwerte anzupassen.You can use simple enumerations when you do not need to customize the enumeration's data contract name and namespace and the enumeration member values.

Hinweise zu einfachen EnumerationenNotes on Simple Enumerations

Wenn Sie das EnumMemberAttribute-Attribut auf einfache Enumerationen anwenden, hat dies keine Auswirkung.Applying the EnumMemberAttribute attribute to simple enumerations has no effect.

Es ist unerheblich, ob Sie das SerializableAttribute-Attribut auf die Enumeration anwenden.It makes no difference whether or not the SerializableAttribute attribute is applied to the enumeration.

Die Tatsache, dass die DataContractSerializer-Klasse das NonSerializedAttribute-Attribut berücksichtigt, das auf Enumerationsmember angewendet wird, gilt nicht für das Verhalten von BinaryFormatter und SoapFormatter.The fact that the DataContractSerializer class honors the NonSerializedAttribute attribute applied to enumeration members is different from the behavior of the BinaryFormatter and the SoapFormatter. Beide Serialisierungsprogramme ignorieren das NonSerializedAttribute-Attribut.Both of those serializers ignore the NonSerializedAttribute attribute.

FlagenumerationenFlag Enumerations

Sie können das FlagsAttribute-Attribut auf Enumerationen anwenden.You can apply the FlagsAttribute attribute to enumerations. In diesem Fall kann eine Liste von null oder mehr Enumerationswerten gleichzeitig gesendet oder empfangen werden.In that case, a list of zero or more enumeration values can be sent or received simultaneously.

Wenden Sie dazu das DataContractAttribute-Attribut auf die Flagenumeration an, und markieren Sie dann alle Member, die Potenzen von 2 sind, mit dem EnumMemberAttribute-Attribut.To do so, apply the DataContractAttribute attribute to the flag enumeration and then mark all the members that are powers of two with the EnumMemberAttribute attribute. Beachten Sie, dass es sich bei der Progression um eine ununterbrochene Folge mit Potenzen des Werts 2 handeln muss (beispielsweise 1, 2, 4, 8, 16, 32, 64).Note that to use a flag enumeration, the progression must be an uninterrupted sequence of powers of 2 (for example, 1, 2, 4, 8, 16, 32, 64).

Die folgenden Schritte gelten für das Senden des Enumerationswerts eines Flags:The following steps apply to sending a flag's enumeration value:

  1. Versuchen Sie, einen Enumerationsmember zu finden (mit angewendetem EnumMemberAttribute-Attribut), der dem numerischen Wert zugeordnet ist.Attempt to find an enumeration member (with the EnumMemberAttribute attribute applied) that maps to the numeric value. Wenn Sie einen Member finden, senden Sie eine Liste, die nur diesen Member enthält.If found, send a list that contains just that member.

  2. Versuchen Sie, den numerischen Wert so zu einer Summe aufzulösen, dass Enumerationsmember vorhanden sind (jeweils mit angewendetem EnumMemberAttribute-Attribut), die den einzelnen Teilen der Summe zugeordnet sind.Attempt to break the numeric value into a sum such that there are enumeration members (each with the EnumMemberAttribute attribute applied) that map to each part of the sum. Senden Sie die Liste mit allen Membern dieser Art.Send the list of all these members. Beachten Sie, dass die gierige Algorithmus wird verwendet, um solche Auffinden einer und daher besteht keine Garantie, die eine Summe gefunden wird, auch wenn es vorhanden ist.Note that the greedy algorithm is used to find such a sum, and thus there is no guarantee that such a sum is found even if it is present. Um dieses Problem zu verhindern, sollten Sie sicherstellen, dass es sich bei den numerischen Werten der Enumerationsmember um Potenzen von 2 handelt.To avoid this problem, make sure that the numeric values of the enumeration members are powers of two.

  3. Lösen Sie eine SerializationException aus, wenn die vorausgehenden zwei Schritte fehlschlagen und der numerische Wert ungleich 0 ist.If the preceding two steps fail, and the numeric value is nonzero, throw a SerializationException. Senden Sie die leere Liste, wenn der numerische Wert 0 ist.If the numeric value is zero, send the empty list.

BeispielExample

Das folgende Enumerationsbeispiel kann für einen Flagvorgang verwendet werden.The following enumeration example can be used in a flag operation.

[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 

Die folgenden Beispielwerte werden dabei wie angegeben serialisiert.The following example values are serialized as indicated.

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.

Siehe auchSee Also

DataContractSerializer
Verwenden von DatenverträgenUsing Data Contracts
Angeben von Datenübertragung in DienstverträgenSpecifying Data Transfer in Service Contracts