C # Idioms:enum or enum class (enum Class)

Source: Internet
Author: User
Tags bool comparison constant constructor range reference serialization
C # Idioms:enum or enum class (enum Class)

Marshine

(Original composition format: http://www.marshine.com)

Reversion:2004/5/28
Modification Note: Thanks to the CLS compatibility issue mentioned by Ninputer, while modifying the Equals rewrite not mentioned in the original version, and modifying the imperfect code of "= =" overload and adding the enum struct content

Reversion:2004/6/4

Add the flags feature of the enum mentioned by KIRC because the text is very long and the new version can be read on http://www.marshine.com.



Representation of a constant type

In a system, there are often attributes whose value is a fixed set of values, and their range is closed (a limited number), such as country code (each country has a unique code, while the number of countries in a certain period is determined), gender type (male, female). In modern programming languages, a typical representation is an enumeration type (enum). An enum represents the type of enclosing range, often supported directly by the program language as a data type, such as c,c#. The enum supported by C # provides type-safe capabilities based on C, and the following are the gender enumeration types defined in C #:

public enum Sex {
Male,
Female,
}

Java does not support enum data types, and Java believes that C provides an enum that is not type-safe, and typically uses a design pattern called Typesafe Enum class to achieve a similar effect (see [JOSHUA01] P80,item21:replace Enum constructs with classes). The Enum class does not allow external constructor instance members (constructors are private) to provide static type member instances to represent the enclosing domain. Using the Enum class method to represent the sex type can be defined as follows (C #):

public class sex{
The sealing of the domain of the private construction guarantee
Private Sex () {
}

Pubic static readonly Sex Male = new Sex ():
Pubic static readonly Sex Female = new Sex ():
}

As with enums, constant properties can be accessed using Sex.male or sex.female, unlike static constant fields (such as static strings, integers), and enum and enum classes can provide strongly typed compile Time checks and provides better data encapsulation and code readability. For example, use constant types to set and compare property values:

Setting property values
Sex Sex = Sex.male;
Comparison
if (sex = = Sex.male) {
// ... ...
}

If the sex is defined with an enum, the value of the enum field is actually compared, and if the sex is defined using the Enum class, the reference address of the static instance member is compared, but the Equals method can be used to compare.

Although the enum class is derived from the Java design pattern, it is not meaningless in C # because the Enum class provides a more powerful capability than the enum type.

Comparison of enum and Enum class

Both enum and Enum classes provide the ability to encapsulate constants, enable strong type checking at compile time, and prevent illegal values using a closed domain. However, because of the different implementation mechanisms, these two approaches also have different characteristics.

An enum in C # is a value type (value) whose base type must be an integer type (such as Int16), so the enum also has the advantage of a value type--more efficient than a reference type (Reference type) and simple to define. However, its disadvantages do not implement custom behavior and cannot provide more properties for constants.

Enum class has no such restriction, although the Enum class itself is not designed to be inherited, However, you can modify the behavior of the base class (System.Object) to provide richer capabilities (such as modifying the ToString method, depending on the localized country name of the user's local language output), or providing additional properties. For example, we provide a list of candidate countries, in addition to showing the country name, can provide country code, language code information.

Problem with Enum class

But Enum class also has its drawbacks, and the Enum class in the design above is compared by the same static member reference address in the process, but after deserializing a serialized enum class instance, the CLR creates a new instance. This causes the deserialized value not to be equal to the pre-serialization value:

IFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter ();

MemoryStream stream = new MemoryStream ();
Serialization of Sex.male values
Formatter. Serialize (stream, Sex.male);
Stream. Seek (0,seekorigin.begin);
Deserialization
Sex Sex = (Sex) formatter. Deserialize (stream);
Console.WriteLine (Sex = = Sex.male);

The code above will output false. So there's a limit to how you can use references, which is a tricky problem in Java, and you need to modify the behavior of deserialization (see [joshua01]p171). C # is not the same as the Java implementation mechanism, cannot modify the deserialized behavior to return the same constant instance, but C # provides the ability to overload operator, we can solve this problem by overloading operator "=", while maintaining CLS compatibility and consistent with the behavior of equals, You also need to overwrite the Equals method:

[Serializable]
public class sex{
Sex type name
private string Sexname;

The sealing of the domain of the private construction guarantee
Private Sex (string sexname) {
This.sexname = Sexname;
}

public static readonly Sex Male = new Sex ("Male");
public static readonly Sex Female = new Sex ("Female");

Provides overloaded "= =" operators, using Sexname to determine whether the same sex type
public static BOOL operator = = (Sex op1, Sex op2) {
if (Object.Equals (OP1, NULL)) return object.equals (OP2, NULL);
return OP1. Equals (OP2);
}

public static bool operator!= (Sex op1,sex op2) {
Return! (OP1 = = OP2);
}

public override bool Equals (object obj) {
Sex Sex = obj as Sex;
if (obj = null) return false;
return sexname = = Sex.sexname;
}

public override int GetHashCode () {
return Sexname.gethashcode ();
}
}

With operator overloading, reference addresses are no longer used to compare constants, but rather by value comparisons (such as the sexname above), which requires that each constant instance must have a unique identity value. In languages that do not support operator overloading, you cannot use "= =" to compare two constant values for equality, instead of using the Equals method.

Design of Enum class

The Enum class generally complies with the following rules:

Private constructors to ensure that class instances cannot be created externally (and that the class cannot be inherited).
Static read-only instance fields represent constants.
Overloaded operator "= =" to ensure that the serialized value can be more equal. Overloads of the "= =" operator must be implemented when passing between processes, such as a distributed application, or when serialization is required.
Rewrite the Equals method to keep the "= =" behavior consistent with equals. (rewriting equals generally also rewrites the GetHashCode method)
In addition, the ToString method is often rewritten to provide a friendly name, Because both Java and. NET use the ToString Method (tostring method in Java) output as the default object display string when binding or displaying an object, such as binding a sex array to a ListBox or using Console.Write output. The following code overwrites the ToString method to provide a friendly display of output:

public class sex{
... ...
public override string ToString () {
return sexname;
}
}

Of course, we can also use ToString to provide localized support to return a string of local languages.

Enum class Another common duty is to provide type conversions between different value systems, such as when reading a value from a database, using the Parse method to convert the value in the database to a constant instance of the object system, and the value type to which the method is converted to the database at store time:

public class sex{
... ...
Returns the type instance based on a string that matches the specified format.
public static Sex Parse (string sexname) {
Switch (sexname) {
Case "Male": return Male;
... ...
}
}

Returns the value of the data store.
public string Todbvalue () {
return sexname;
}
}

Use an enum or enum Class?

Depending on the characteristics of the enum and enum class, we can decide whether to use an enum or an Enum class based on the requirements for the constant type.

The following scenarios are appropriate for using an enum:

Constant types are used for internal representations and are not used to display names.
Constant values do not need to provide additional properties. For example, just know the country code without having to get other attributes of the country
The Enum class can be applied to more scenarios:

Often used for types that can provide friendly information. Displays the type names supported by localization, or displays names that are inconsistent with the enumeration name, for example, Country.chn can be displayed as "".
More constant properties are provided.
To provide richer behavior. such as the Parse method.
Groups the constants. such as Country.asia include Asian countries.
Using struct to represent enumerations

If the range is not closed, but you want to provide some constants, you can also use struct, such as the system default color settings in the System.Drawing.Color structure. Using struct to design the enum value has no intrinsic difference with the Enum class method, only the struct must provide the parameterless constructor, so the closed domain can not be realized.

Reference:

[JOSHUA01]

Effective Java programming Language Guide, Joshua Bloch, Pearson education,2001.
Java Efficient Programming Guide (Chinese Edition), Machinery Industry Press, 2002



Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.