[C #]

Source: Internet
Author: User

[C #]

 

Written by Allen Lee

 

I know your pain is my promise. You told me to indulge. Silence is because of inclusiveness. If you want to leave, please remember me; if you are sad, please forget me. -- Jay Chou, excuses

 

0. Origin

This article is written due to netwy's "the default value of Enumeration type variables must be 0!".

 

1. Problem

// Code #01

Class Tester
{
Static void Main ()
{
Alignment a = new Alignment ();
Console. WriteLine (a. ToString ("D "));

Alignment B = Alignment. Left;
Console. WriteLine (B. ToString ("D "));
}
}

If Left is the first member of the Alignment enumeration, do you think the two methods for initializing enumeration variables are equivalent? If they are not equivalent, what are their differences?

 

2. Comparison of the two initialization Methods

2.1 The value of the first enumerated member is 0.

If we do not specify the value of the first Member for Alignment:

// Code #02

Enum Alignment
{
Left,
Center,
Right
}

The output result of Code #01 is:

0
0

We decompile the Main Code #01 into IL:

// Code #03

. Method private hidebysig static void Main (string [] args) cel managed
{
. Entrypoint
// Code Size: 50 byte (s)
. Maxstack 2
. Locals (
CsWritingLab. Alignment alignment1,
CsWritingLab. Alignment alignment2)
L_0000: nop
L_0001: ldc. i4.0
L_0002: stloc.0
L_0003: ldloc.0
L_0004: box CsWritingLab. Alignment
L_0009: ldstr "D"
L_000e: call instance string [mscorlib] System. Enum: ToString (string)
L_0013: call void [mscorlib] System. Console: WriteLine (string)
L_0018: nop
L_0019: ldc. i4.0
L_001a: stloc.1
L_001b: ldloc.1
L_001c: box CsWritingLab. Alignment
L_0021: ldstr "D"
L_0026: call instance string [mscorlib] System. Enum: ToString (string)
L_002b: call void [mscorlib] System. Console: WriteLine (string)
L_0030: nop
L_0031: ret
}

From the code above, we can see that the two initialization methods are equivalent. Essentially, the following four statements (at this time) are equivalent (they generate the same IL code ):

Alignment a = new Alignment ();
Alignment B = Alignment. Left;
Alignment d = (Alignment) 0;
Alignment c = 0;

2.2 The value of the first enumerated member is not 0

What if we manually specify the value of the first member of Alignment?

// Code #04

Enum Alignment
{
Left = 1,
Center,
Right
}

The output result of Code #01 is somewhat confusing:

0
1

Why? Let's look at the IL code to see how the compiler understands the Main at this time:

// Code #05

. Method private hidebysig static void Main (string [] args) cel managed
{
. Entrypoint
// Code Size: 50 byte (s)
. Maxstack 2
. Locals (
CsWritingLab. Alignment alignment1,
CsWritingLab. Alignment alignment2)
L_0000: nop
L_0001: ldc. i4.0
L_0002: stloc.0
L_0003: ldloc.0
L_0004: box CsWritingLab. Alignment
L_0009: ldstr "D"
L_000e: call instance string [mscorlib] System. Enum: ToString (string)
L_0013: call void [mscorlib] System. Console: WriteLine (string)
L_0018: nop
L_0019: ldc. i4.1
L_001a: stloc.1
L_001b: ldloc.1
L_001c: box CsWritingLab. Alignment
L_0021: ldstr "D"
L_0026: call instance string [mscorlib] System. Enum: ToString (string)
L_002b: call void [mscorlib] System. Console: WriteLine (string)
L_0030: nop
L_0031: ret
}

From the above IL code, we can see that the two initialization methods are no longer understood as the same. By comparing Code #03 and Code #05, you will find that only row L_0019 is changed:

Ldc. i4.0-> ldc. i4.1

That is to say, when the first member of enumeration is used to initialize enumeration variables, the compiler can make corresponding adjustments according to enumeration definitions to compile the code that meets our expectation. This approach actually uses the thought of polymorphism.

At this time,

Alignment a = new Alignment ();

Equivalent

Alignment a = (Alignment) 0;

Or

Alignment a = 0;

 

3. new: default constructor of value type and default value of Value Type

Generally, we use new to call the Instance Constructors of the reference type, or Non-Default Instance Constructors of the custom value type ). However, we can also use new to call the default constructor of the value type (including built-in simple type and custom type), for example:

Int I = new int ();

Here, new calls the default int constructor to initialize I to the corresponding default value -- 0. Of course, this default constructor is automatically provided by. NET (but you cannot provide it manually ). That is to say, to use new to call the default constructor of the value type, the value type will be automatically set to the corresponding default value .. NET value types include Simple types, Enum types, and Struct types ).

3.1 default value of Simple types

For Simple types, their default values are shown in the following table:

Simple Type Default Value
Bool False
Byte 0
Char '\ 0'
Decimal 0.0 M
Double 0.0D
Float 0.0F
Int 0
Long 0L
Sbyte 0
Short 0
Uint 0
Ulong 0
Ushort 0

3.2 default value of Enum types

For Enum types,. NET automatically converts the literal 0 (literal 0) to the corresponding Enumeration type.

3.2.1 There is a 0-value member

If a member of the enumeration type is assigned a value of 0 (not the first member), the value stored in the enumerated variable is the value of the member. Assume that Alignment members are assigned the following values:

// Code #06

Enum Alignment
{
Left = 1,
Center = 0,
Right = 2
}

So, the following sentence

Alignment a = new Alignment ();

Will be equivalent

Alignment a = Alignment. Center;

3.2.2 no member with 0 values

If no member of the enumeration type is 0, for example

// Code #07

Enum Alignment
{
Left = 1,
Center = 2,
Right = 3
}

So

Alignment a = new Alignment ();

Will be equivalent

Alignment a = (Alignment) 0;

Or

Alignment a = 0;

In this case, the stored values of enumerated variable a can be called non-predefined Enumerated (member) values.

3.2.3 two or more 0-value members

What if more than one member in the enumeration type is assigned a value of 0? For example

// Code #08

Enum Alignment
{
Left = 0,
Center = 1,
Right = 0
}

Can you guess the running result of the following code?

// Code #09

Alignment a = new Alignment ();
Console. WriteLine (a. ToString ());

From the running result of the code, we can see that new gives the Alignment. Left "configuration" to the enumerated variable. Now let's look at the following code:

// Code #10

String a = Enum. GetName (typeof (Alignment), 0 );
Console. WriteLine (a. ToString ());

In fact, the output results of Code #10 and Code #09 are the same, from. NET source code, we can also see that the rule for selecting an object is to use Array first. sort (Array keys, Array items); sorts the enumerated Member names and their values, and then cyclically selects the first lucky winner.

3.3 default value of the structure type (Struct types)

For the structure type (Struct types), the value type fields contained in the structure are initialized to the corresponding default value, and the reference type fields are initialized to null.

// Code #11
// See Code #02 for Alignment.

Public struct MyStruct
{
Public int Integer;
Public Alignment Align;
Public string Text;
}

The following code:

MyStruct m = new MyStruct ();
Console. WriteLine (m. Integer );
Console. WriteLine (m. Align );
Console. WriteLine (m. Text = null );

The running result of is:

0
Left
True

 

4. How do you think enumeration is appropriate?

Now, I forget all the previous articles and seriously consider this question:

How do you think enumeration is appropriate?

Well, this is a very big question. It is beyond my ability to answer the question comprehensively. If I barely answer it, I must be generous. But I cannot ignore it, so I have to use my ideas as a reference.

The essence of Taiji lies in its philosophy rather than its manipulation. A body without thoughts is like walking dead. The most basic role of a language is communication. To communicate successfully, you must first have an idea and then use the language rules to express it to your audience to achieve the purpose of communication. The effect of communication depends on your familiarity with the language rules and your skills in application.

The same is true for programming languages. It is not only a bridge between you and your computer, but also a bridge between you and the next code maintainer. Maybe your code is legal, because the computer can understand it, but this does not mean that your code is friendly, because the next code maintainer may be confused. Easily, if you want to maintain the work of a person, you may have to play a bench early. I think you absolutely have the responsibility to think about the next code maintainer. Furthermore, the next code maintainer may be yourself. I wonder if you have experienced any strange feelings when you review your previous code after a long period of time?

Each language has a hidden minefield and traps. For some reason, people cannot completely clear these mines and traps. For the sake of the masses, people hide these annoying things, but you just need to dig them out to find out. In this gray area, the boundaries between right and wrong are very vague. Many things are neither prohibited nor recommended, so silence may be the best choice. "Silence is because of inclusiveness". However, this is why you say "you said to me to indulge. Savor Jay Chou's "excuse", and you may also feel helpless.

The world we live in is so complex that we can't fully understand it yet, but we have never missed any opportunity to explore. Scattered and scattered knowledge can hardly help us to better understand the world. What we need is a structured and systematic knowledge system to help us better understand the nuances of the world. Rational classification allows us to better organize existing knowledge, and each classification method presents relevant knowledge from one aspect, this allows us to use these associated knowledge more effectively.

I think an enumeration type is a classification method. It allows you to view your target group from a certain aspect. For a given string Class, we can view it from the perspective of FontStyle Enumeration or Alignment Enumeration) it can also be analyzed from the KnownColor Enumeration perspective. Our actions should be for a certain purpose. If you have no idea why you want to do so, then it may be the most appropriate to not do so.

Looking back at what we have mentioned above, do you think it is really necessary to use new to initialize enumeration variables? If enumeration represents a classification idea, why do you need to take the risk of Storing non-predefined enumeration (member) values in enumeration variables (as possible) (see section 3.2.2 )?

At the end of this article, I would like to say

Whether something is useful depends on whether you use it; whether it is effective depends on whether you use it correctly. Please use the advantageous aspect of language to assist our work, rather than hurting ourselves and others.

 

See Also:

  • Allen Lee, [C #, IL, BCL]

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.