This article is just my personal summary, Do not spray
First of all, string is the reference type.
String s_a = "yhc ";
String s_ B = s_a;
If (s_a.Equals (s_ B ))
Console. WriteLine ("same? ");
Else
Console. WriteLine ("different ");
The output is "same", letS_ B = s_aIn essence, s_ B points to the storage location of yhc on the stack. At this time, both s_a and s_ B point to the storage location of yhc on the stack.
Theoretically, if you modify the value of s_a, for example, s_a = "wq", B will also change, but actually it is not. in c, if you modify the value of a string object such as s_a, the system will re-apply for a memory for s_a to store the modified s_a value wq, B still points to a's previous memory location.
This is why stringbuilder is recommended for frequent string operations, because stringbuilder can dynamically increase the memory size, similar to the standard library string in c ++, in c #, the string is of a fixed size. If you assign a fixed memory space to an object of string size, this object cannot be changed once it is created. If you want to add content to it, I have to create a new string object, copy the value, and delete the previous string object. Frequent string operations will reduce the efficiency. After all, create an object and allocate memory, deleting an object consumes resources.
We can determine this conclusion by comparing the memory address.(The ReferenceEquals static method is used to compare whether the object references are consistent, rather than a simple value.) If s_a and s_ B point to the same address, the comparison here should return the same
S_a = "wq ";
If (ReferenceEquals (s_a, s_ B ))
Console. WriteLine ("same ");
Else
Console. WriteLine ("different ");
Obviously, the output is "different", which indicates that the system re-allocates the memory space of the new address for s_a. Of course, you may say why not =, because after the string = is overwritten, it is actually a string value (of course, if you must use =, it is also possible, but you only need to pack it into the object type, let = no longer overwrite the comparison for the special case of string, that is, if (object) s_a) = (object) s_ B ))), however, this is not the case when = is compared with other objects. This is a point where the string reference type represents the value type feature. In fact, there is also a point where the string type also represents the value type feature, when the string type is passed as a parameter, the reference address of the string object is passed, but modifying the value of the string object in the passed method does not affect the ontology, this is because the system re-constructs a New string object based on the transmitted address, such as calling method void fun (string a) and passing s_a as a parameter. A will be assigned another address by the system, instead of pointing to the address of s_a, which is a special case of the reference type. For example, A is A common class, such
A B = new ();
B. name = "yhc ";
Fun (B );
// The code runs here. If output, the name value of a is: wq
Void fun (A)
{
// The code runs here. If output, the name of Output a is yhc.
A. name = "wq"; // because the parameter passes the reference of B, the operation on a is the operation on B.
// The code runs here. If output, the name value of a is: wq
}
But if so:
A B = new ();
B. name = "yhc ";
Fun (B );
// The code runs here. If output, the name value of a is output:Yhc
Void fun (A)
{
// The code runs here. If output, the name of Output a is yhc.
A = newA ();
A. name = "wq ";
// The code runs here. If output, the name value of a is: wq
}
After the execution of fun (B), the output is no longer wq, because in method fun, we direct a to A newly created object a on the stack, this new object will be recycled by the GC garbage collection mechanism after it leaves the function method, and it will not be known when it will be recycled. Of course, if the resource is created on the stack, it will be immediately released, however, there are also some special cases about GC collection of objects created on the stack, that is, those unmanaged objects, such as SqlConnection database connections, file handles, and network connections, these objects are not recycled by GC after they are new in the method.
As mentioned above, we go back to the previousOf course, some people will say that the ReferenceEquals is not profound enough and accurate, because the value also changes after s_a is changed to wq, And the ReferenceEquals cannot be used to determine whether the values are different or different references, so we modified the following: according to the principle that the system will automatically allocate new memory space for the string, we changed s_a to yhc, that is, although it was modified, however, the value is still the original yhc, only to test whether the modification operation has re-allocated memory space
S_a = "yhc ";
If (ReferenceEquals (s_a, s_ B ))
Console. WriteLine ("same ");
Else
Console. WriteLine ("different ");
We all thought that the output would be "different", but the result was disappointing. The system output was "the same" because Microsoft's CLR used the optimization technology called the string resident technology, the principle of this technology may be known to all, that is, during CLR initialization, an internal hash will be created. The table is in the form of a key value and the key is a string. For example, yhc, the value is the address of yhc stored in the heap memory. The hash list must be empty during initialization. During JIT compilation, the yhc string is first obtained from the hash list, if yhc is not found for the first time, it will open up space on the stack to store yhc, store the address and yhc string in the hash, and then go to the next time, here, the value of s_a is changed to yhc, and yhc is found in the hash key, so no memory is allocated to store the modified yhc, instead, let s_a still point to the space where the previous yhc is stored on the stack. That is to say, the modified s_a = "yhc" has not changed, or yhc, so it is optimized by the compiler's optimization mechanism. Therefore, this test still fails to test the effect we want.
We know the principles of the defects tested above,However, we almost forgot what we were trying to test. We were trying to test s_a or s_ B and then the system re-allocated the memory space for it, we need to compare whether the space addresses of the modified two are consistent, so we will summarize the above lessons as follows:
S_a = string. Copy (s_ B)
If (ReferenceEquals (s_a, s_ B ))
Console. WriteLine ("same ");
Else
Console. WriteLine ("different ");
Here, s_a = string. Copy (s_ B), the string. Copy method is to create a System. String with the same value as the specified s_ BNewInstance. Note that it is a new instance. With this method, the compiler will not optimize the above string resident technology, that is, s_a is modified again, the modified value is the value of s_ B (the value of s_ B is yhc), that is, the value of s_a is also yhc. At this time, the system outputs "different, this verifies that after the string object is modified, the system will re-allocate the memory space for it.
The complete test code is as follows:
The test is very simple, but I have learned a lot from it.
String s_a = "yhc ";
String s_ B = s_a;
S_a = string. Copy (s_ B );
If (ReferenceEquals (s_a, s_ B ))
Console. WriteLine ("same ");
Else
Console. WriteLine ("different ");
Console. Read ();