Marshine
(Original layout format: http://www.marshine.com)
Reversion: 2004/5/28
Change Description: ThanksNinputerThe CLs compatibility problem was mentioned. At the same time, the equals rewriting not mentioned in the original version was modified, and the modification "=" was not complete.Code, And add Enum struct content
Reversion: 2004/6/4
Added the flags feature of the enum mentioned by kirc because the text is too long and the new version can be read on the http://www.marshine.com.
Constant type Representation
In the system, attribute values are usually fixed and their value ranges are closed (a limited number of values), such as country code (each country has a unique code, in a certain period of time, the number of countries is determined), gender type (male, female ). In modern times ProgramIn the language, a typical expression is Enumeration type (Enum).EnumIndicates the type of the closed value field, which is often directly supported by the program language as a data type, suchC,C #.C #SupportedEnumInCProvides the type security capability.C #Gender Enumeration type defined:
Public Enum sex {
Male,
Female,
}
JavaNot SupportedEnumData type,JavaThinkCProvidedEnumIt is not of type security.Typesafe Enum classTo achieve similar results (see[Joshua01] P80, item21: replace Enum constructs with classes).Enum classInstance members cannot be constructed externally (the constructor isPrivate. UseEnum classMethodSexThe type can be defined as follows (C #):
Public class sex {
//Private structure ensures the closeness of value ranges
Private sex (){
}
Pubic static readonly sex male = new sex ():
Pubic static readonly sex female = new sex ():
}
SameEnumYou can useSex. MaleOrSex. FemaleTo access constant attributes, which is different from static constant fields (such as static strings and integers ),EnumAndEnum classProvides strongly typedCompile timeChecks and provides better data encapsulation and code readability. For example, you can use the constant type to set and compare the property values:
//Set attribute values
Sex sex = sex. Male;
//Comparison
If (sex = sex. Male ){
//......
}
IfSexYesEnumDefined, the above comparison is actuallyEnumField Value; ifSexYesEnum classIf it is defined, it compares the reference addresses of static instance members. Of course, you can also useEqualsMethod.
AlthoughEnum classIs fromJavaBut inC #Is not meaningless, becauseEnum classProvidesEnumMore powerful type capabilities.
EnumAndEnum classComparison
EnumAndEnum classBoth provide the ability to encapsulate constants and enable strong type check during compilation. Use closed value fields to prevent invalid values. However, because of the different implementation mechanisms, these two methods also have different characteristics.
EnumInC #Is a value type (Value TypeThe base type must be an integer (for exampleInt16), SoEnumIt also has the advantages of Value Type--Than the reference type (Reference Type) Higher efficiency and simple definition. However, its disadvantage is that it cannot implement custom behaviors and cannot provide more attributes of constants.
Enum classThere is no such restriction, althoughEnum classIt is not designed to inherit, but can modify the base class (System. ObjectTo provide more capabilities (such as modifying ).TostringMethod, according to the local language of the user output localized country name), you can also provide more attributes . For example, we provide a list of candidate countries. Besides displaying country names, we can provide country code and language code information.
Enum classProblems
HoweverEnum classIt also has its disadvantages.Enum classThe static member reference addresses in the process are the same for comparison, but when a serializedEnum classAfter the instance is deserialized,CLRA new instance is created, causing the deserialization value not equal to the pre-serialization value:
Iformatter formatter = new system. runtime. serialization. formatters. Binary. binaryformatter ();
Memorystream stream = new memorystream ();
//SerializationSex. MaleValue
Formatter. serialize (stream, sex. Male );
Stream. Seek (0, seekorigin. Begin );
//Deserialization
Sex sex = (sex) formatter. deserialize (Stream );
Console. writeline (sex = sex. Male );
The above code will be outputFalse. Therefore, the reference method has limitations.JavaThis is a tricky issue and the deserialization behavior needs to be modified (see[Joshua01] p171).C #AndJavaThe implementation mechanism is different, and the same constant instance cannot be returned by modifying the deserialization behavior, HoweverC #Provides the ability to overload operators. We can use the overload Operators"="To solve this problem, and to maintainCLSCompatibleEqualsAnd must be rewritten.EqualsMethod:
[Serializable]
Public class sex {
//Gender name
Private string sexname;
//Private structure ensures the closeness of value ranges
Private sex (string sexname ){
This. sexname = sexname;
}
Public static readonly sex male = new sex ("male ");
Public static readonly sex female = new sex ("female ");
//Provides"="Operator, useSexnameTo determine whether it is the sameSexType
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 ();
}
}
By using operator overloading, instead of comparing constants with reference addresses, we compare values (as shown above ).SexnameTherefore, each constant instance must have a unique identifier value. In languages that do not support Operator overloading"="To compare whether two constant values are equal. Instead, useEqualsMethod.
Enum classDesign
Enum classGenerally, the following rules are met:
- private constructor ensures that class instances cannot be created externally (and classes cannot be inherited ).
- the static read-only instance field represents a constant.
- overload operator "=" ensures that the serialized values are equal. When inter-process transmission (such as distributed applications) or serialization is required, the "=" operator must be overloaded.
- rewrite equals method, keep "=" Behavior consistent with equals . (Rewrite equals the gethashcode method > )
In addition, it is often rewrittenTostringMethod To provide display friendly names, becauseJavaAnd. NetUsed when binding or displaying objectsTostringMethod (JavaIsTostringMethod) output as the default object display string, for exampleSexBind an arrayListBoxOr useConsole. WriteOutput. The following code is rewritten:TostringMethod To provide friendly display output:
Public class sex {
......
Public override string tostring (){
Return sexname;
}
}
Of course, we can also useTostringProvides Localization support and returns strings in the local language.
Enum classAnother common responsibility is to provide type conversion between different value systems, such as usingParseMethod to convert the value of the database to a constant instance of the Object System, while the method provided during storage is converted to the value type of the database:
Public class sex {
......
//Returns an instance of the type according to a string in the specified format.
Public static sex parse (string sexname ){
Switch (sexname ){
Case "male": Return male;
......
}
}
//Return the value of data storage.
Public String todbvalue (){
Return sexname;
}
}
UseEnumOrEnum class?
AccordingEnumAndEnum classCan be determined based on the requirements for constant types.EnumOrEnum class.
Applicable to the following scenariosEnum:
- The constant type is used for internal representation and is not used to display the name.
- A constant value does not need to provide additional attributes. For example, you only need to know the country code, and do not need to obtain other attributes of the country.
Enum classApplicable to more scenarios:
- It is often used to provide friendly information. For example, if the type name supported by localization is displayed, or the name is different from the enumerated name, for exampleCountry. CHNCan be displayed"China".
- Provides more constant attributes.
- Provides richer behaviors. For exampleParseMethod.
- Groups constants. For exampleCountry. AsiaIncluding Asian countries.
UseStructTo indicate Enumeration
If the value range is not closed, but you want to provide some constants, you can also useStruct, SuchSystem. Drawing. ColorSystem default color settings in the structure. UseStructTo designEnumSame ValueEnum classThere is no essential difference between methods, justStructYou must provide a non-parameter constructor, so you cannot implement a closed value range.
Refer:
[Joshua01]
Valid Java programming language guide, Joshua Bloch, Pearson Education, 2001.
Java efficient programming guide (Chinese version), Mechanical Industry Press, 2002