C # packing and unpacking [sorting]),

Source: Internet
Author: User
Tags unpack

C # packing and unpacking [sorting] (conversion ),

// 1. // packing and unpacking are an abstract concept. // 2. // packing converts the value type to the reference type; binning converts a reference type to a value type. // you can use the binning and unboxing functions to convert any value of the allowed value type to the value of the Object type, link the // value type with the reference type // For example: int val = 100; object obj = val; Console. writeLine ("object value = {0}", obj); // This is a packing process, which is the process of converting the value type to the reference type int val = 100; object obj = val; int num = (int) obj; Console. writeLine ("num: {0}", num); // This Is A unpacking process, which converts the value type to the reference type, conversion from the reference type to the value type // Note: Only objects that have been packed in a box can be split. // 3 ,//. in. NET, data types are divided into value types and references (not the same as pointers in C ++) types, Correspondingly, the internal/memory allocation is divided into two methods: Stack and heap. Note: It is managed heap. // The value type is only allocated in the stack. // Allocate memory and managed heap for the reference type. // The managed heap corresponds to garbage collection. // 4: What is packing/unpacking? // Packing: used to store value types in the garbage collection heap. Packing is an implicit conversion from the value type to the object type or to any interface type of the value type. // Unpack: the explicit conversion from the object type to the value type or from the interface type to the value type of the interface. // 5: Why is packing required? (Why convert the value type to the reference type ?) // The most common scenario is to call a method containing parameters of the Object type. This Object can be of any type: // for general purpose. You need to pack a value type (such as Int32. // Another usage is that a non-generic container defines the element type as // Object to ensure universality. Therefore, to add the value type data to the container, You need to pack the data. // 6: binning/unboxing internal operations. // Binning: // assign an object instance to the heap and copy the value to the new object. Step by step. // Step 1: allocate new managed heap memory (the size is the value type instance size plus a method table pointer and a // SyncBlockIndex ). // Step 2: copy the instance field of the value type to the newly allocated memory. // Step 3: return the address of the newly allocated object in the managed heap. This address is a reference to the object. // Someone understands this: If Int32 is packed, the returned address points to an Int32. I don't think it can be understood in this way, but it does have a problem. First, it is not comprehensive. Second, it points to Int32 and does not state its essence/(in the managed heap ). // Unpack: // check the object instance to make sure it is a boxed value of the given value type. Copy the value from the instance to the value type variable. // As mentioned in the book, unpacking only gets the pointer to the value type in the referenced object, while copying the content is triggered by the value assignment statement. I think it doesn't matter. The most important thing is to check the nature of the object instance. The binning and packing types must be matched //. At this point, on the IL layer, I cannot see the principle. I guess, maybe a method similar to GetType is called to retrieve the type for matching (because strict matching is required ). // 7: Effect of packing/unpacking on execution efficiency // obviously, from the principle, we can see that during packing, a brand new referenced object is generated, which will consume time, that is, // reduces the efficiency. // What should I do? // First, avoid packing as much as possible. // For example, you can avoid both of the above two cases. In the first case, you can avoid this by using the overload function. Second, you can avoid this by using generics. // Of course, everything cannot be absolute. If the code you want to transform is a third-party assembly and you cannot change it, you can only pack it. // For the optimization of the packing/unpacking code, because C # is implicit in both packing and unpacking, the fundamental method is to analyze the // code, the most direct method of analysis is to understand how to view the decompiled IL code. For example, extra packing may exist in the loop // body. You can simply use the advance packing method for optimization. // 8: a better understanding of packing/unpacking // It is not as simple and clear as described above. For example, it becomes a reference object when packing, there will be an extra square // table pointer. What is the use of this? // We can further explore through examples. // Example. Struct A: ICloneable {public Int32 x; public override String ToString () {return String. format ("{0}", x) ;}public object Clone () {return MemberwiseClone () ;}} static void main () {A a;. x = 100; Console. writeLine (. toString (); Console. writeLine (. getType (); A a2 = (A). clone (); ICloneable c = a2; Ojbect o = c. clone () ;}// 5.0:. toString (). The compiler finds that A overwrites the ToString method and directly calls the ToString directive. Because A is A value type, the compiler does not show polymorphism. Therefore, it is called directly without packing. // (Note: ToString is the base class System of. the ValueType method. // 5.1:. getType (), GetType is inherited from System. to call the ValueType method, // a method table pointer is required. Therefore, a is boxed to generate a method table pointer and call the // System of the base class. valueType. (ADD, all value types are inherited from System. ValueType ). // 5.2: a. Clone (). Because A implements the Clone method, no packing is required. // 5.3: ICloneable Transformation: When a2 is converted to the interface type, it must be packed because the interface is a reference class // type. // 5.4: c. Clone (). You do not need to pack it. Call the packed objects in the previous step in the managed stack. // Appendix: in fact, the above is based on a fundamental principle, because the unboxed value type does not have a method table pointer, so, cannot // call the inherited virtual method on the value type. In addition, the interface type is a reference type. In this regard, my theory // solution, the table pointer of this method is similar to the virtual function table pointer of C ++. It is an important // basis for implementing the polymorphism mechanism of referenced objects. // 9: how to change a boxed object // For a boxed object, because the specified method cannot be called directly, you must unpack the object before calling the method, however, a new stack instance will be generated after the binning is performed //, and The binning object cannot be modified. A little dizzy. I feel like I'm talking about tongue twisters. For example: (append the change method in the preceding example) public void Change (Int32 x) {this. x = x;} // call: A a = new A ();. x = 100; Object o = a; // bind it to o. below, you want to change the o value. (A) o). Change (200); // has it been changed? Not changed. // The reason why I didn't get rid of it is that o generated A temporary stack instance A during unpacking. Therefore, the change was based on temporary A and did not change it to the packing object. // (Appendix: In the hosted C ++, the instance reference obtained in the first step can be directly removed and removed, but it is changed directly, but C # // does not work .) // What should I do? // Well, the same effect can be achieved through the interface method. // Implementation: interface IChange {void Change (Int32 x);} struct A: IChange {...} // Call :( (IChange) o). Change (200); // do you get rid of it? Get rid of it. // Why can I change it now? // When converting o to IChange, it will not be packed again here. Of course, it will not be split because o is already of the reference type, and it is of the IChange type, therefore, you can directly call Change. Therefore, the changed fields in the already // boxed object are used to achieve the expected results. // 10, ------------------------ // to convert the value type to the reference type, you need to perform the boxing operation: // 1. First, allocate memory for the newly generated reference object from the managed heap. // 2. copy the data of the value type to the allocated memory. // 3. Return the address of the newly allocated object in the managed heap. // You can see that the memory allocation and data copy operations that affect performance are performed for one packing operation. // To convert the reference inner type to the value inner type, unboxing is required: // 1. First, obtain the address of the field of the value type in the managed heap, this step is strictly case-removing. // 2. Copy the value in the reference object to the value type instance on the thread stack. // After the two steps, it can be considered that the same boxing is an inverse operation. In a strict sense, unpacking does not affect the performance, but // subsequent data copying operations will affect the performance as in boxing operations. // 11, ------------------------- // all types of NET are composed of the base class System. object Inheritance, including the most common basic types: int, // byte, short, bool, etc., that is, all things are objects. If you declare that all these types of memory are allocated in the // HEAP, the efficiency will be extremely low! (The medium reason and the difference between stack and stack will be discussed separately in another article !) // How does. NET solve this problem? By dividing a type into a value type and a reference type // (regerencetype ), the value types defined in C # include the original type (Sbyte, Byte, Short, // Ushort, Int, Uint, Long, Ulong, Char, Float, Double, Bool, // Decimal), enumeration (enum), structure (struct), reference types include: Class, array, interface, Delegate, // string and so on. // The value type is used to allocate memory in the stack. It is initialized at the same time as the Declaration to ensure that the data is not NULL. // The reference type is used to allocate memory in the heap and the initialization is null, the reference type requires the garbage collection to/recycle memory. The value type is not used. If it exceeds the scope, the system will automatically release it! // The following is the definition of packing and unpacking! // Packing is to implicitly convert a value type to a reference object. For example: int I = 0; Syste. Object obj = I; // This process is packed! It is to pack I! // Binning is to convert a referenced object into any value type! For example: int I = 0; System. object obj = I; int j = (int) obj; // The first two sentences in this process are packing I, and the last one is unpacking obj! 1,

 

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.