C # basics: in-depth research based on const and readonly

Source: Internet
Author: User

• Both readonly and const are [1] used to identify constants.
• Const can be used to modify the field of the class or a local variable (local variable), while readonly is only used to modify the field of the class.
• The value of a const constant must be clear and constant during compilation, but the value of a readonly constant is a little different, that is, the value can be compiled at runtime. Of course, it must also comply with the constraint as a constant, that is, the value must be constant.
• A const constant must be assigned a value while being declared, and the value must be fixed and constant during compilation; the readonly constant can choose to assign a fixed value to it during compilation at the same time as needed, or assign the initialization work of its value to the instance constructor) complete. For example, public readonly string m_Now = DateTime. Now. ToString ();, m_Now changes with the actual situation during running.
• Const constants belong to the class level rather than the instant object level, and cannot be used together with static, the value of this constant will be shared by all instance objects of the entire class (For details, refer to the Remark area later ).
• Readonly constants can be class-level or Instance Object-level, depending on its declaration and implementation of initialization. Readonly can be used in combination with static to specify that the constant belongs to the class level and submit the initialization work to the static constructor) complete (for details about how to declare a readonly constant as a class or instance object level, see the Remark area later ).
• The types that can be declared as Constants by const must be the following primitive types: sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, float, bool, decimal, string.
• Objects, arrays, and structures cannot be declared as const constants.
• In general, the reference type cannot be declared as a const constant, but there is an exception: string. The value of the const constant of the reference type can be string or null. In fact, although the string type is a reference type,. NET has special processing on it. This kind of processing is called the immutable character string, so that the string value has the read-only feature. For the constant character string content, refer to Microsoft. NET Framework programming (revision).
Examples:

Copy codeThe Code is as follows: Code
Using System;
Publicclass Order
{
Public Order ()
{
Guid guid = Guid. NewGuid ();
ID = guid. ToString ("D ");
}
// For each order, the order number is a constant determined in real time.
Style = "color: #008000;">
Publicreadonlystring ID;
Publicoverridestring ToString ()
{
Return "Order ID:" + ID;
}
}

Explaintion:
• If used in combination with the database, ID field is usually associated with the primary key of a table, such as the OrderID of the Orders table.
• The primary keys of the database are generally in the following three ways:
• Auto increment value. You can set DataColumn. AutoIncrement to true to activate the auto-increment feature.
• Unique name. This is to generate a unique serial number using a defined algorithm.
• GUID (globally unique identifier ). You can use the System. Guid structure to generate a GUID, as shown in the preceding example.Copy codeThe Code is as follows: Code
Using System;
Class Customer
{
Public Customer (string name, int kind)
{
M_Name = name;
M_Kind = kind;
}
Publicconstint NORMAL = 0;
Publicconstint VIP = 1;
Publicconstint SUPER_VIP = 2;
Privatestring m_Name;
Publicstring Name
{
Get {return m_Name ;}
}
Privatereadonlyint m_Kind;
Publicint Kind
{
Get {return m_Kind ;}
}
Publicoverridestring ToString ()
{
If (m_Kind = SUPER_VIP)
Return "Name:" + m_Name + "[SuperVip]";
Elseif (m_Kind = VIP)
Return "Name:" + m_Name + "[Vip]";
Else
Return "Name:" + m_Name + "[Normal]";
}
}

• In general, if you need to declare constants that are universally recognized and used as a single, such as the circumference rate, golden split ratio, and so on. You can consider using const constants, such as public const double PI = 3.1415926 ;. If you need to declare a constant, but this constant will be determined according to the actual running situation, the readonly constant will be a good choice, such as the Order number Order in the first example above. ID.
• If you want to represent the internal default values of an object, and such values are usually constant values, you can also consider const. More often, when we refactor the source code (using Replace Magic Number with Symbolic Constant), the impact of the Magic Number will be attributed to this feature of const.
• For the question of whether the variables modified by readonly and const belong to the class level or the Instance Object level, let's take a look at the following code:Copy codeThe Code is as follows: Code
Using System;
Namespace ConstantLab
{
Class Program
{
Staticvoid Main (string [] args)
{
Constant c = new Constant (3 );
Console. WriteLine ("ConstInt =" + Constant. ConstInt. ToString ());
Console. WriteLine ("ReadonlyInt =" + c. ReadonlyInt. ToString ());
Console. WriteLine ("InstantReadonlyInt =" + c. InstantReadonlyInt. ToString ());
Console. WriteLine ("StaticReadonlyInt =" + Constant. StaticReadonlyInt. ToString ());
Console. WriteLine ("Press any key to continue ");
Console. ReadLine ();
}
}
Class Constant
{
Public Constant (int instantReadonlyInt)
{
InstantReadonlyInt = instantReadonlyInt;
}
Publicconstint ConstInt = 0;
Publicreadonlyint ReadonlyInt = 1;
Publicreadonlyint InstantReadonlyInt;
Publicstaticreadonlyint StaticReadonlyInt = 4;
}
}

• Use Visual C # When Using intelliisence in Main () to insert fields related to Constant, we find that ReadonlyInt and InstantReadonlyInt need to specify the instance object of Constant; constInt and StaticReadonlyInt must specify the Constant class (see the code above ). It can be seen that the constant modified with const or static readonly belongs to the class level, while the readonly variable can be initialized directly by assigning values or initialized in the instance constructor, all belong to the Instance Object level.
• In general, if you need to express a set of related constants at compilation, you can consider using the enumeration type (enum ), instead of embedding multiple const constants directly into the class as the field, there is no absolute superiority or inferiority between the two methods.Copy codeThe Code is as follows: Code
Using System;
Enum CustomerKind
{
SuperVip,
Vip,
Normal
}
Class Customer
{
Public Customer (string name, CustomerKind kind)
{
M_Name = name;
M_Kind = kind;
}
Privatestring m_Name;
Publicstring Name
{
Get {return m_Name ;}
}
Private CustomerKind m_Kind;
Public CustomerKind Kind
{
Get {return m_Kind ;}
}
Publicoverridestring ToString ()
{
Return "Name:" + m_Name + "[" + m_Kind.ToString () + "]";
}
}

However, this code, combined with enumeration and conditional judgment, hinders your more flexible expansion and may increase maintenance costs in the future. You can replace it with polymorphism, use Replace Conditional with Polymorphism to refactor the code.
Comments:
• Readonly field should be accurately translated into a "Read-Only domain". This is to unify the translation term so that the modified amount of both the field and the const are described as "constants", hoping to avoid misunderstanding.

Working Principle
Readonly is the runtime constant. It is assigned a value when the program is running. It cannot be changed after the value is assigned. Therefore, some people call it a read-only variable.
Const is the compile-time constant. During program compilation, constant values are parsed and all constant references are replaced with corresponding values.
The following two constants are declared:Copy codeThe Code is as follows: public static readonly int A = 2; // A indicates the running time
Public const int B = 3; // B indicates the compile time.

The following expression:
Int C = A + B;
After compilation, it is equivalent to the following form:
Int C = A + 3;
As you can see, const constant B is replaced with the word surface volume 3, while readonly constant A remains the reference mode.
Declaration and initialization
The readonly constant can only be declared as a class field. It supports instance type or static type. It can be initialized at the same time of Declaration or in the constructor. After initialization, it cannot be changed.
In addition to being declared as a class field, const constants can also be declared as local constants in methods. The default value is static type (without static modification; otherwise, compilation errors will occur ), however, initialization must be completed at the same time as the declaration.
Supported Data Types
Const constants are replaced with literal values during compilation, which limits their value types. Const constants can only be assigned numbers (integers, floating-point numbers), strings, and enumeration types. The following code cannot be compiled:Copy codeThe Code is as follows: public const DateTime D = DateTime. MinValue;

Change to readonly to compile normally:Copy codeThe Code is as follows: public readonly DateTime D = DateTime. MinValue;

Maintainability
Readonly works in reference mode. After a constant is updated, all the places that reference this constant can get the updated value.
Const is a little more complex, especially for cross-assembly calls:Copy codeThe Code is as follows: public class Class1
{
Public static readonly int A = 2; // A indicates the running time.
Public const int B = 3; // B indicates the compile time.
}
Public class Class2
{
Public static int C = Class1.A + Class1. B; // The value of variable C is the sum of A and B.
}
Console. WriteLine (Class2.C); // output "5"

Assume that Class1 and Class2 are in two different sets, and now change the constant value in Class1:Copy codeThe Code is as follows: public class Class1
{
Public static readonly int A = 4; // A indicates the running time.
Public const int B = 5; // B indicates the compile time.
}

Compile and deploy Class1 (Note: Class2 is not re-compiled at this time), and check the value of variable C again:Copy codeThe Code is as follows: Console. WriteLine (Class2.C); // output "7"

The result may be a little unexpected. Let's take a closer look at the value assignment expression of variable C:Copy codeThe Code is as follows: public static int C = Class1.A + Class1. B;

After compilation, it is equivalent to the following form:Copy codeThe Code is as follows: public static int C = Class1.A + 3;

Therefore, no matter how the value of constant B changes, it will not affect the final result. Although re-compiling Class2 can solve this problem, at least we can see the possible maintenance problems caused by const.
Performance Comparison
Const is directly involved in the operation in literal form, and the performance is slightly higher than readonly, but for general applications, this performance difference can be said to be minimal.
Applicable scenarios
In the following two cases:
A. The value remains unchanged permanently (such as the circumference rate, the number of hours in a day, and the Earth's radius)
B. Strict Program Performance Requirements
You can use the const constant. In other cases, the readonly constant should be used first.
Although you have been writing C # code for many years, when someone asks about the difference between your const and readonly, it may take a while ~
When I was reading the. Net programmer interview book of the European version, I found that I had been confused about the two for a long time. Indeed, const and readonly are similar. They declare the variables as read-only and cannot be rewritten after the variables are initialized. So what are the differences between the const and readonly modifiers? In fact, this involves two different constant types in C #: compile-time constants and runtime constants ). The two have different characteristics. Incorrect use will not only result in loss of efficiency, but also cause errors.
First, explain what is a static constant and what is a dynamic constant. A static constant is a constant that is parsed by the compiler during compilation and replaced with the initial value. The value of a dynamic constant is obtained at the moment of running. during compilation, it is marked as a read-only constant instead of a constant value, in this way, Dynamic Constants do not need to be initialized during declaration, but can be delayed to initialization in the constructor.
When you have a general understanding of the two concepts above, you can describe const and readonly. The constant modified by const is the first one in the preceding section, that is, the static constant, and readonly is the second one, that is, the dynamic constant. The difference can be achieved through the characteristics of static constants and dynamic constants.Note:
1) const-modified constants must be initialized during Declaration; readonly-modified constants can be delayed until the constructor is initialized.
2) const-modified constants are parsed during compilation, that is, the constant value is replaced with the initial value. readonly-modified constants are delayed until running.
In addition, the const constant can be declared in the class or in the function body, but the static readonly constant can only be declared in the class.
Some beginners may be confused by the above purely conceptual explanation. The following are some examples:Copy codeThe Code is as follows: using System;
Class P
{
Static readonly int A = B * 10;
Static readonly int B = 10;
Public static void Main (string [] args)
{
Console. WriteLine ("A is {0}, B is {1}", A, B );
}
}

What is the output result of the above Code? Many people think that A is 100 and B is 10! In fact, the correct output result is A is 0 and B is 10. Well, if it is changed to the following:Copy codeThe Code is as follows: using System;
Class P
{
Const int A = B * 10;
Const int B = 10;
Public static void Main (string [] args)
{
Console. WriteLine ("A is {0}, B is {1}", A, B );
}
}

What is the output result of the above Code? Is it A is 0, B is 10? In fact, it is wrong again. The correct output result is A is 100 and B is 10.
So why? As mentioned above, const is A static constant, so the values of A and B are determined during compilation (that is, when the value of B is 10, and A = B * 10 = 10*10 = 100), the output in the Main function is of course A is 100, B is 10. Static readonly is A dynamic constant. The variable value is not parsed during compilation. Therefore, it is the default value at the beginning. For example, if both A and B are of the int type, they are all 0. When the program runs to A = B * 10; so A = 0*10 = 0, and the program then runs to B = 10, the true initial value 10 of B is assigned to B. If you still don't know clearly, we can use the ILDASM tool provided by Microsoft to open it by entering ILDASM under Vs 2008 Command, as shown below:

Open the executable files generated after the above two codes are compiled, as shown in:


Static readonly executable program structure

Const

Executable program structure

The constants A and B are displayed in the preceding two figures. Double-click the node to see the difference:

Constant A modified by static readonly

Const-modified constant

Constant B modified by static readonly

Const-modified constant B
It can be seen that the const modified constant has calculated the nominal values of A and B during compilation, while the static readonly modified constant is not parsed, therefore, the Main function has the following differences:

Main function of the static readonly Program

Main function of the const Program

From the Main function, we can see that the output of the const program is 100 and 10, while the readonly program does P: A and P: B in the output, it is determined that the values of constants A and B are delayed until they are run, so the output is 0 and 10.
So what are the characteristics of Static and Dynamic Constants? In fact, static constants can only be declared as simple data types (int and floating-point type), enumeration, Boolean, or string type, while Dynamic Constants can also modify some object types. For example, the DateTime type is as follows:
// Error
Const DateTime time = new DateTime ();
// Correct
Static readonly DateTime time = new DateTime ();
The above error is that you cannot use the new keyword to initialize a static constant, even if it is a value type, because new will cause the value to be determined at runtime, which is contrary to the fixed literal value at the time of static variable compilation.
The comparison between static constants and Dynamic Constants is shown in the following table:

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.