From the perspective of CLR, the value type and reference type, and the clr type reference

Source: Internet
Author: User
Tags mscorlib

From the perspective of CLR, the value type and reference type, and the clr type reference
Preface

Most of the sample code in this article comes from CLR via C # Edition3, which is summarized and simplified. This article focuses on several common problems, I will not explain the details in depth.

A few days ago, I have been busy translating questions about heap and stack in memory. The blog "C # heap vs stack" is exactly where I have produced a lot of Why in the process of writing this article, therefore, I first translated and learned some C/C ++ knowledge, which will help solve some puzzles outside the CLR and hope to help you more.

 

It is inevitable that there will be deviations or errors in understanding the knowledge. If you have any questions or errors, please reply ~~~

Different value types and reference types

The types in C # are divided into Value Type and Reference Type ).

Sample One:

Public void SampleOne () {SomeClass r1 = new SomeClass (); // reference type, which is allocated on the managed stack. SomeStruct v1 = new SomeStruct (); // value type, allocated on the thread stack. R1.X = 5; // modify the value of the reference type to 5 v1.X = 5; // modify the x value of the value type to 5 Console. writeLine (r1.X); // The result shows "5" Console. writeLine (v1.X); // The result shows "5 "}

SampleOne simply changes the content of the value type and reference type, and there is nothing special about it. It corresponds to the Thread Stack and Managed Heap of the program) the only thing to note is that "r1" itself represents "reference to an object SomeClass in the managed heap (pointer = value type)". If it is difficult to understand, see Article C # stack vs stack.

  

 

Sample Two:

  

Public void SmapleTwo () {SomeClass r1 = new SomeClass (); // reference type, which is allocated on the managed stack. SomeStruct v1 = new SomeStruct (); // value type, allocated on the thread stack. R1.X = 5; // modify the value of the reference type to 5 v1.X = 5; // modify the x value of the value type to 5 SomeClass r2 = r1; // only copy reference (r1 pointer) SomeStruct v2 = v1; // copy v1 to generate the new object v2 r1.X = 8 on the stack; // both r1.X and r2.X change, because it points to the same address content v1.X = 9; // v1.X changes, while v2.X does not change the Console. writeLine (r1.X); // The result shows "8" Console. writeLine (r2.X); // The result shows "8" Console. writeLine (v1.X); // The result shows "9" Console. writeLine (v2.X); // The result shows "5 "}

In SampleTwo, the result is that the value type is a copy action, the new object is on the stack, and there is no impact between the new and old objects. The reference type copies the pointer to the object ", the Pointer Points to the same address, so changing r1.X will affect r2.X.

 

Packing and unpacking

The above section describes the differences between the C # value type and the reference type in terms of behavior. A series of efficiency discussions caused by the value type "Box" operation.

Why packing and unpacking?

The prototype of many functions in the Framework is designed as an Object parameter, which leads to the conversion of many value types into Object reference types, this results in packing and later unpacking operations (of course, many prototypes implement parameter overloading or generic methods of value types to avoid packing/unpacking operations ).

For example, the prototype of the Add method of System. Collection. ArrayList is public virtual int Add (object value );

First, copy p fields in the thread stack to the managed stack, and generate two types of Object Pointer and Synchronous Index fast, and then return the type object pointer p' to the Add method, for example:

The newly generated objects in the managed heap are completely independent of the original object p in the thread stack, and there is no correlation between the two lifecycles.

Finally, when var p = (Point) a [0] is used, the object is converted to the Point type for unpacking. The binning process is opposite to packing: The reference type in the managed heap is copied to the thread stack as the value type before being used.

Obviously, both Box and UnBox operations will adversely affect the performance of the program. We should avoid such problems.

Use IL to prove the hypothesis

Sample One:

Public int RunSample1 () {var v = 5; object o = v; // Box v = 123; Console. writeLine (v + "," + (Int32) o); // Fisrt 'V' boxed, and 'O' boxed. return v; # region IL Generate Code //. method public hidebysig instance void RunSample1 () cel managed // {// code size 47 (0x2f )//. maxstack 3 //. locals init ([0] int32 v, // [1] object o) // IL_0000: nop // IL_0001: ldc. i4.5 // IL_0002: stloc.0 // IL_0003: ldloc.0 // IL_0004: box [mscorlib] System. int32/IL_0009: stloc.1 // IL_000a: ldc. i4.s 123 // IL_000c: stloc.0 // IL_000d: ldloc.0 // IL_000e: box [mscorlib] System. int32/IL_0013: ldstr "," // IL_0018: ldloc.1 // IL_0019: unbox. any [mscorlib] System. int32 // IL_001e: box [mscorlib] System. int32 // IL_0023: call string [mscorlib] System. string: Concat (object, // object, // object) // IL_0028: call void [mscorlib] System. console: WriteLine (string) // IL_002d: nop // IL_002e: ret //} // end of method BoxAndUnBox: Run # endregion}

The following conclusions are drawn from SampleOne:

Sample Two:

Public Point RunSample2 () {var p = new Point (1, 1); Console. writeLine (p); // Box, show 1, 1 p. offset (2, 2); // Change Point-> 3, 3 Console. writeLine (p); // Box, show 3, 3 object o = p; // Box Console. writeLine (o); // Show 3, 3 (Point) o ). offset (3, 3); // UnBox and Change Point-> 6, 6 Console. writeLine (o); // Show 3, 3 return (Point) o; // UnBox and Copy a instance for return # region IL Generate Code //. method public hidebysig instance valuetype [System. drawing] System. drawing. point // RunSample2 () cel managed // {// code size 94 (0x5e )//. maxstack 3 //. locals init ([0] valuetype [System. drawing] System. drawing. point p, // [1] object o, // [2] valuetype [System. drawing] System. drawing. point CS $1 $0000, // [3] valuetype [System. drawing] System. drawing. point CS $0 $0001) // IL_0000: nop // IL_0001: ldloca. s p // IL_0003: ldc. i4.1 // IL_0004: ldc. i4.1 // IL_0005: call instance void [System. drawing] System. drawing. point ::. ctor (int32, // int32) // IL_000a: nop // IL_000b: ldloc.0 // IL_000c: box [System. drawing] System. drawing. point // IL_0011: call void [mscorlib] System. console: WriteLine (object) // IL_0016: nop // IL_0017: ldloca. s p // IL_0019: ldc. i4.2 // IL_001a: ldc. i4.2 // IL_001b: call instance void [System. drawing] System. drawing. point: Offset int32 (, // int32) // IL_0020: nop // IL_0021: ldloc.0 // IL_0022: box [System. drawing] System. drawing. point // IL_0027: call void [mscorlib] System. console: WriteLine (object) // IL_002c: nop // IL_002d: ldloc.0 // IL_002e: box [System. drawing] System. drawing. point // IL_0033: stloc.1 // IL_0034: ldloc.1 // IL_0035: call void [mscorlib] System. console: WriteLine (object) // IL_003a: nop // IL_003b: ldloc.1 // IL_003c: unbox. any [System. drawing] System. drawing. point // IL_0041: stloc.3 // IL_0042: ldloca. s CS $0 $0001 // IL_0044: ldc. i4.3 // IL_0045: ldc. i4.3 // IL_0046: call instance void [System. drawing] System. drawing. point: Offset int32 (, // int32) // IL_004b: nop // IL_004c: ldloc.1 // IL_004d: call void [mscorlib] System. console: WriteLine (object) // IL_0052: nop // IL_0053: ldloc.1 // IL_0054: unbox. any [System. drawing] System. drawing. point // IL_0059: stloc.2 // IL_005a: br. s IL_005c // IL_005c: ldloc.2 // IL_005d: ret //} // end of method BoxAndUnBox: RunSample2 # endregion}

Conclusion:

SampleThree:

Public bool RunSample3 () {var p = new MyPoint (1, 1); // Define struct type object o = p; Console. writeLine (p. toString (); // Not Box (IMyPoint) p ). change (2, 2); // When turn to interface it shoshould boxed and copy a instance. console. writeLine (p); // Show 1, 1 (IMyPoint) o ). change (2, 2); // 'O' is a reference type, it not boxed. console. writeLine (o); // Show 2,2 return (MyPoint) o ). x. equals (p. x); # region IL Generate Code //. method public hidebysig instance bool RunSample3 () cel managed // {// code size 115 (0x73 )//. maxstack 3 //. locals init ([0] valuetype Demo_CLRVIACSHARP.MyPoint p, // [1] object o, // [2] bool CS $1 $0000, // [3] int32 CS $0 $0001) // IL_0000: nop // IL_0001: ldloca. s p // IL_0003: ldc. i4.1 // IL_0004: ldc. i4.1 // IL_0005: call instance void Demo_CLRVIACSHARP.MyPoint ::. ctor (int32, // int32) // IL_000a: nop // IL_000b: ldloc.0 // IL_000c: box Demo_CLRVIACSHARP.MyPoint // IL_0011: stloc.1/IL_0012: ldloca. s p // IL_0014: constrained. demo_CLRVIACSHARP.MyPoint // IL_001a: callvirt instance string [mscorlib] System. object: ToString () // IL_001f: call void [mscorlib] System. console: WriteLine (string) // IL_0024: nop // IL_0025: ldloc.0 // IL_0026: box Demo_CLRVIACSHARP.MyPoint // IL_002b: ldc. i4.2 // IL_002c: ldc. i4.2 // IL_002d: callvirt instance void metadata: Change (int32, // int32) // IL_0032: nop // IL_0033: ldloc.0 // IL_0034: box metadata // IL_0039: call void [mscorlib] System. console: WriteLine (object) // IL_003e: nop // IL_003f: ldloc.1 // IL_0040: castclass Demo_CLRVIACSHARP.IMyPoint // IL_0045: ldc. i4.2 // IL_0046: ldc. i4.2 // IL_0047: callvirt instance void metadata: Change (int32, // int32) // IL_004c: nop // IL_004d: ldloc.1 // IL_004e: call void [mscorlib] System. console: WriteLine (object) // IL_0053: nop // IL_0054: ldloc.1 // IL_0055: unbox. any Demo_CLRVIACSHARP.MyPoint // IL_005a: ld1_int32 Demo_CLRVIACSHARP.MyPoint: x // IL_005f: stloc.3 // IL_0060: ldloca. s CS $0 $0001 // IL_0062: ldloca. s p // IL_0064: ld1_int32 Demo_CLRVIACSHARP.MyPoint: x // IL_0069: call instance bool [mscorlib] System. int32: Equals (int32) // IL_006e: stloc.2 // IL_006f: br. s IL_0071 // IL_0071: ldloc.2 // IL_0072: ret //} // end of method BoxAndUnBox: RunSample3 # endregion}

Conclusion:

 

Summary

 

Welcome to the official website ~~~

 

Update:

After reading the comments at, I collapsed ~~~ There is also my reason here, because I wrote the previous "C # heap vs stack" series, so in this article, there is not much explanation process, but it is directly replaced by conclusion and conclusion, the final point of view in this article is:The behavior of value type and reference type should be analyzed from the storage location of the object, so that we can understand the value type and reference type.. Which of the following statements about the value type on the stack and the reference type on the stack? Please read the article carefully.

In the end, I thought it wasI fan an incorrect summary.The object encapsulated on the stack as a reference type (Box Operation) is displayed as a reference behavior, it is concluded that "the storage location is different, and the behavior is also different, in the end, we can better understand the conclusions of the value type and the reference type, and ignore the behavior of the value type directly included by the reference type on the stack.

At, May 16, Eric Lippert's explanation is used as the final summary.

Http://blogs.msdn.com/ B /ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx.

English: http://www.cnblogs.com/kirinboy/archive/2012/06/15/value-and-reference-in-csharp-2.html

 

Download Sample Code

 

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.