C # idioms: ENUM or ENUM CLASS (enumeration class)
Marshine (Original version format: http://www.marshine.com)
Reversion: 2004/5/28 Modified Description: Thank Ninputer
The CLS compatible problem mentioned, and the original version did not mention the Equals rewriting, and modify the "==" overloaded informative code, and increase the ENUM STRUCT content.
Reversion: 2004/6/4
Increase the enums feature mentioned by KIRC, because the text is long, the new version can be read in http://www.marshine.com.
Constant type
There is often some attribute values for some attributes in the system that are fixed set of values, and their value domain is closed (limited number), such as country code (the only code of each country, and the number of countries in a certain period is determined) ), Gender type (male, female). In a modern program language, a typical representation is an enumeration type (Enum). ENUM represents the type of closed value domain, often supported by the program language as a data type, such as C, C #, and the like. C # supported Enum provides types of security based on C, which is the gender enumeration type defined with C #:
Public Enum Sex {Male, Female,}
Java does not support ENUM data types, Java believes that the ENU provided is not type security, usually used in designing models called TypeSafe Enum Class to get similar effects (see [Joshua01] P80, Item21: Replace Enum constructs with classes . Enum class does not allow external construction instance members (constructor private), providing a static type member instance to represent a closed value domain. Use the Enum class to indicate that the SEX type can be defined as follows (C #):
Public class sex {// Private construct guaranteed value of closed private sex () {} pubic static readonly sex male = new sex (): pubic static readonly sex female = new sex ():}
Like ENUM, you can use SEX.MALE or SEX.FEMALE to access constant attributes, which are different from static constant fields (such as static strings, integers), enum, and enum clas, can provide strong types of compile TIME checks and provide more Good data encapsulation and code readability. For example, use constant type settings and compare attribute values:
// Set the attribute value SEX SEX = sex.male; // Compare IF (SEX == SEX.MALE) {// ... ...}
If SEX is defined using enum, the above comparison is actually the value of the Enum field; if SEX is defined using the enum class, it is compared to a reference address of a static instance member, of course, can also use the equals method. Comparison.
Although ENUM CLASS is from Java design mode, it is not meaningful in C #, because Enum Class provides more powerful than ENUM type.
Comparison of ENUM and ENUM CLASS
ENUM and Enum Class provide the ability to encapsulate constants, which can achieve strong type checks in compile, and prevent illegal values using the closed value domain. However, these two methods have different characteristics because of the different mechanisms. ENUM is a value type in C #, whose base type must be an integer type (such as INT16), so the Enum also has the advantages of value type - higher efficiency than reference types (Reference Type), It is simple to define. However, its shortcomings cannot achieve custom behavior, which cannot provide more properties for constants.
ENUM CLASS has no such limit, although the Enum class itself is not designed to be inherited, but can modify the behavior of the SYSTEM.Object to provide a richer ability (such as modifying the toString method, output according to the user's local language Localized country names can also provide more properties. For example, we provide a list of candidates, in addition to displaying the country name, national code, language code information.
ENUM CLASS problem
However, ENUM CLASS also has its shortcomings, and the ENUM Class is compared in the process of static member reference addresses in the process, but the CLR creates a new instance when the serialized Enum Class instance is deserved. Thus, the deceleration value is not equal to the phenomenon of serialization value:
IFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter (); MemoryStream stream = new MemoryStream (); // serialized Sex.Male value formatter.Serialize (stream, Sex.Male); stream.Seek ( 0, seekorigin.begin); // Deverse sex sex = (sex) formatter.deSerialize (stream); console.writeline (sex == sex.male);
The above code will output False. Therefore, it is limited by reference, which is a more tricky problem in Java, which requires a modification of deserialized behavior (see [Joshua01] P171). C # is different from Java's implementation mechanism, and cannot return the same constant instance by modifying the reverse sequence-based behavior, but C # provides the ability to operate overload, we can solve this problem by the overload operator "==", In order to keep CLS compatibility and consistent with Equals, it is also necessary to overwrite the equals method:
[Serializable] public class sex {// gender type name private string sexname; // Private construct Guarantee Value Domain Closed Private Sex (String SexName) {this.SexName = Sex Name;} public static readonly sex male = new sex (" MALE "); public static readonly sex feedale = new sex (" female "); // Provides an overloaded" == "operator, use sexname to determine if it is 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 ();}} Re-uses a reference address by operator, but is compared to comparison (as SEXNAME above), so that each constant instance must have a unique identifier value. In the language that does not support operator overload, "==" cannot be used to compare whether the two constant values are equal, but should be replaced with the equals method.
ENUM CLASS design
ENUM CLASS is generally in line with the following rules:
Private constructor to ensure that the external unable to create class instances (simultaneously can't inherit the class).
The static read-only instance field represents a constant.
The overload operator "==", ensuring that the serialized value can be equal. The overload of the "==" operator is required when the process is delivered (eg, a distributed application) or serialization.
Keep the Equals method, keep "==" behavior and equals match. (Rewriting Equals is generally rewriting the GetHashCode method)
In addition, the TOSTRING method is usually overwritten to provide a friendly name, because Java and .NET use the toString method when binding or displaying an object (Java to TSTRING method) output as the default object display string, For example, bind the SEX array to ListBox or use console.write output. The following code rewrites the toString method to provide the output of friendly display:
Public class sex {... public override string toString () {return sexname;}}
Of course, we can also provide localized support with TOSTRING, return a string of local languages. ENUM CLASS Another common responsibility is to provide type conversion between different value systems. If you read the value from the database, use the PARSE method to convert the database median to the constant instance of the object system, and provide a method in storage Convert to the value type of the database:
Public Class Sex {... // Returns the type instance according to a string that meets the specified format. Public Static SEX PARSE (STRING SexName) {switch (sexname) {copy "male": return Male; ...}} // Returns the value of the data store. Public String Todbvalue () {return sexname;}}
Is ENUM or ENUM CLASS?
According to ENUM and ENUM CLASS, we can decide to use ENUM or Enum Class based on the requirements of constant types.
The following scenarios are suitable for using ENUM:
The constant type is used for internal representation and is not used to display the name.
Constant values do not need to provide additional properties. For example, you only need to know the country code, do not need other properties of the country.
Enum Class can apply to more scenarios:
Commonly used in the type of friendly information. If the localized support type name is displayed, or the name is inconsistent with the enumeration name, such as country.chn, can be displayed as "China".
Provide more constant properties.
Provide a richer behavior. Such as the Parse method.
Grouping constants. Such as Country.asia includes Asian countries.
Use struct to indicate enumeration
If the value domain is not closed, it is desirable to provide some constants, or you can use struct, such as the system default color settings in the System.Drawing.color structure. The use of Structs to design the ENUM value does not differ in the ENUM CLASS mode, just Struct must provide a parameter constructor, so the closed value field cannot be implemented.
reference:
[Joshua01]
Effective Java Programming Language Guide, Joshua Bloch, Pearson Education, 2001.JAVA Efficient Programming Guide (Chinese), Machinery Press, 2002
Author Blog:
http://blog.9cbs.neet/marshine/