CLR via C # Deep solution note Three-primitive type, reference type, and value type | Type and Member Basics | Constants and Fields

Source: Internet
Author: User
Tags new set microsoft c

primitive types for programming languagesSome data types are so common that many compilers allow code to manipulate them in simplified syntax.  System.Int32 a = new System.Int32 (); A = 0a = 1; Equivalent to: int a = 1; this syntax not only enhances the readability of the Code, it generates IL code that is exactly the same as the IL code generated when using System.Int32. The data types that the compiler supports directly are called primitive types (primitive type). Primitive types map directly to types that exist in the Framework class library (FCL). As in C #, int directly maps the System.Int32 type. The language specification for C # says: "In style, it's best to use keywords rather than full system type names." "In fact, it might be better to use the FCL type name to avoid using primitive type names." The CLR supports two types: reference types and value types. Most types in the FCL are reference types, but the most used by programmers are value types. Reference typeThe reference type is always allocated from the managed heap, and the new operator of C # returns the memory address of the object-that is, the memory address that points to the object data. When using reference types, you need to be aware of some performance issues, namely the fact that, #1, memory must be allocated from the managed heap, and every object allocated on the heap has some extra members that must initialize # #, the other bytes in the object (set for the field) are always set to zero # #, and when an object is allocated from the managed heap May force a garbage collection operation value typeTo maximize performance and improve the performance of simple, common types, the CLR provides a lightweight type called value type. Value types are typically allocated on the thread stack (because they are also embedded as fields in an object of a reference type). In a variable that represents an instance of a value type, it does not contain a pointer to the instance. Conversely, a variable of a value type contains the field (value) of the instance itself, and then the field in the action instance is no longer required to pick up a pointer. Instances of value types are not controlled by the garbage collector. The benefits of design and use of value types are as follows: #1, easing the pressure in the managed heap # #, reducing the number of garbage collection applications that the application needs to make during its memory period custom value types cannot have a base type, but can implement one or more interfaces. In addition, all value types are implicitly sealed (sealed) to prevent a value type from being used as a base type for any other reference type or value type. When designing your own type, consider carefully whether a type should be defined as a value type, rather than as a reference type. At some point, value types can provide better performance. Value types do not allocate memory on the heap, so once the methods that define instances of that type are not active, the storage allocated for them is freed, which also means that instances of the type will not receive a notification through the Finalize method when their memory is reclaimed. how the CLR controls the layout of fields in a typeTo improve performance, the CLR can arrange fields of the type in whatever way it chooses. For example, the CLR can rearrange the order of fields in memory, grouping object references into groups, and correctly arranging and populating data fields. However, when you define a type, for each field of the type, you can indicate whether the CLR is in the order in which you specify it, or in a way that the CLR deems appropriate to rearrange itself. System.Runtime.InteropServices.StructLayoutAttribute. This is reflected in what the CLR-oriented compiler does. For example, the Microsoft C # compiler chooses Layoutkind.auto for reference types (classes) by default, and layoutkind.sequential for value types (structs). Boxing and unpacking of value typesValue types are a type that is lighter than the reference type because they are not allocated as objects in the managed heap, are not garbage collected, and are not referenced by pointers.In many cases, you need to get a reference to an instance of a value type. If you want to get a reference to an instance of a value type, the instance must be boxed. The Add method of the ArrayList object Public Virtual Int32 Add (Object value);Arraylist.add needs to get a reference (or pointer) to an object on the managed heap as a parameter. If a set of Int32 numbers needs to be populated with ArrayList, the Int32 number must be converted to a real object in the managed heap, and a reference to the object is obtained. How to convert a value type to a reference type is to use a mechanism called boxing (boxing). Well, what happens internally when one instance of a value type does a boxing operation: #1, allocate memory in the managed heap. The amount of memory allocated is the amount of memory required for each field of a value type plus two additional members (type object pointers and synchronous block indexes) required by all objects of the managed heap. #2, the value type of the field is copied to the newly allocated pair of memory. #3, returns the address of the object. The address is a reference to this object, and the value type is now a reference type. Note that the lifetime of the boxed value type exceeds the lifetime of the unboxed value type. The FCL now contains a new set of generic collection classes that make a non-generic collection class obsolete. For example, the generic collection classes are greatly enhanced and performance is significantly improved. One of the biggest enhancements is that the generic collection class allows developers to manipulate the collection of value types without boxing/unpacking the items in the collection. In addition to improving performance, you get compile-time type safety, and the source code becomes clearer because of the reduced number of forced type conversions. After packing, the possibility of unpacking is often faced. Unpacking is not about boxing upside down, it costs a lot less than boxing. such as: Int32 i = (Int32) a[0]; Unpacking is a two-step process: #1 to get the address of each field in the boxed object, which is unpacking. #2, copy the values contained in these fields from the heap to the value type instance based on the stack (line stacks).Simply put, if you get a reference to an instance of a value type, the instance must be boxed. This happens when you pass an instance of a value type to a method that needs to get a reference type, as in the Arraylist.add method above. As mentioned earlier, an unboxed value type is more "lightweight" than a reference type. This is due to a few two reasons:#1, they are not allocated on the managed heap. #2, they do not have an extra member for each object on the heap, which is a "type Object pointer" and a "synchronous block index". Therefore, because the unboxed value type does not have a synchronous block index, you cannot use various methods of the System.Threading.Monitor type (or the lock statement for C #) to have multiple threads synchronize access to this instance. a few notes about value types:#1, a value type can override the virtual method of equals, GetHashCode, or ToString, and the CLR can call the method non-virtual because the value types are implicitly sealed (that is, there is no polymorphism) and no type can derive from them. #2, in addition, the instance of the value type used to invoke the method is not boxed. However, if you override the virtual method to invoke the implementation of the method in the base class, the value type instance is boxed when the implementation of the base class is called, so that a reference to a heap object is passed to the base method through the this pointer. #3, when a value type calls a non-virtual, inherited method (such as GetType or MemberwiseClone), the value type is boxed anyway. This is because these methods are defined by System.Object, so these methods expect the this argument to be a pointer to an object on the heap. #4, when an unboxed instance of a value type is transformed into an interface of a type, the instance is required to be boxed. This is because the interface variable must contain a reference to an object on the heap. Testimonials:Any. NET Framework developer can guarantee the long-term success of their own development program only after they have actually understood these concepts. Because only after a deep understanding, you can build efficient applications faster and more easily. Important notes:Members that are defined in a value type should not modify any instance fields of the type. In other words, the value type should be immutable (immutable). In fact, I recommend that you mark fields of value types as readonly. This way, if you accidentally write a method that attempts to change a field, the compilation cannot pass. Because if a method attempts to modify an instance field of a value type, calling this method will produce unintended behavior because of the change in boxing. After constructing the good one value type, if you do not call any method that modifies its state (or if there is no such method at all), you will not have to worry about when boxing and unboxing/field copying will occur. If a value type is immutable, you can simply copy the same state (without worrying about any method that modifies the state), and any behavior of the code will be in your hands. Perhaps you are away from custom value types when you see these nuances of value types, or you have never used a custom value type. However, the core value type of the FCL (Byte, Int32, ...). And all of the enums are "immutable"), and to understand and remember these possible problems, when the code really comes up with these problems, you will know. equality and identity of objectsFor the default implementation of the Equals method of object, it implements the actual identity (identity) rather than equality (equality). Object Hash CodeAn algorithm that allows objects of the same class to have different hash codes as much as possible, but does not mean that different object hash codes are completely different. The hash code is the ID of the object. “ DynamicThe dynamic expression is actually the same type as System.Object. The compiler assumes that any action you make on an expression is legitimate, so no warnings or errors are generated. However, if you attempt to perform an invalid operation at run time, an exception is thrown. type and member base Various members of the typeConstants, fields, instance constructors, type constructors, methods, operator overloads, conversion operators, properties, events, types the visibility of the typePublic: Not only is it visible to all code in its definition assembly, it is also visible to code in other assemblies. Internal: types are visible only to all code in the defined assembly, not to code in other assemblies. If you define a type, the C # compiler defaults to setting the visibility of the type to internal if you do not explicitly specify the visibility of the type. Friend AssemblyWe want the TeamA assembly to have a way to define its tool type as internal, while still allowing the team to teamb access to those types. The CLR and C # provide support in this regard through friend assemblies (friend assembly). If you want to include code in one assembly, and you perform unit tests on internal types in another assembly, the friend Assembly feature can also be useful. Accessibility of membersThe CLR itself defines a set of accessibility modifiers, but each programming language chooses its own set of terms and the appropriate syntax when it applies accessibility to members. For example, the CLR uses assembly to indicate that members are visible to all code within the same assembly, while C # corresponds to the term internal. C #:Private, protected, internal, protected internal, public when a derived type overrides a member defined in its base type, the C # compiler requires that the original member and the overriding member have the same accessibility. That is, if the members in the base class are protected, the overridden members in the derived class must also be protected. However, this is only a limitation of the C # language itself, not the CLR. When deriving from a base class, the CLR allows the accessibility restrictions of members to be relaxed, but the tightening is not allowed. It is not allowed to make access to a base class method more restrictive in a derived class because the CLR promises that derived classes can always be transformed into base classes and gain access to the base class methods. If you allow stricter access restrictions on overridden methods in derived classes, the CLR's commitment cannot be fulfilled. partial classes, structures, and interfacesThis functionality is entirely provided by the C # compiler, and the CLR is ignorant of partial classes, structs, and interfaces. Partial this keyword tells the C # compiler, a class, struct, or interface definition that its source code may be dispersed into one or more source code files. how the CLR calls virtual methods, properties, and EventsMethod represents code that performs some action on an instance of a type or type. Performing an operation on a type, called a static method, or performing an operation on an instance of a type is called a non-static method. Any method has a name, a signature, and a return value (which can be void). visibility of reasonable usage types and accessibility of membersWhen using the. Net framework, the application is most likely composed of types defined by multiple assemblies that use multiple company sound fields. This means that developers have little control over the components they use (assemblies) and the types they define. Developers often do not have access to the source code (even if the component is created in any programming language), and the release of different components is generally based on a different schedule. In addition, because of polymorphic and protected (protected) members, the base class developer must trust the code written by the derived class developer. Of course, the developer of a derived class must also trust code that inherits from the base class. These issues should be carefully considered when designing components and types. Specifically, it is to focus on how to correctly set the visibility of types and the accessibility of members in order to achieve the best results.when defining a new type, the compiler should generate a sealed class by default so that it cannot be used as a base class. However, many compilers, including the C # compiler, generate non-sealed classes by default, which, of course, allows developers to explicitly mark new types as sealed using sealed. Sealing class is better than non-sealed class, there are three reasons: #1, Version control: The class starts to be sealed, in the future can be changed to non-sealed without compromising compatibility. Conversely, otherwise. #2, Performance: Classes are sealed, there is certainly no derived class, when calling a method, it is not necessary to determine which type defines the method to invoke, that is, do not need to find the type of the object at run time, and directly call the virtual method in a non-virtual way. #3, security and predictability: derived classes can override either the virtual method of the base class or directly with the implementation of this virtual method in the base class. Once a method, property, or event is set to virtual, the base class loses some control over its behavior and state.   Here are some of the principles that you'll follow when defining a class:   extended read:  each application uses such or such resources as files, memory buffers, screen space, network connections, database resources, and so on. In fact, in an object-oriented environment, each type represents a resource that can be used by a program. To use these resources, you must allocate memory for the type that represents the resource.   The specific steps required to access a resource are as follows: #1, the IL directive newobj is called to allocate memory for the type that represents the resource. Using the new operator in C #, the compiler automatically generates the directive. #2, initialize the memory, set the initial state of the resource, and make the resource available. The instance constructor of the type is responsible for setting the initial state. #3, access the members of the type (which can be repeated as needed) to use the resource. #4, destroy the state of the resource to clean it up. #5, free up memory. Garbage collection will be solely responsible for this step.   Note that the resources represented by value types (including all enumerated types), collection types, String, Attribute, delegate, and exception do not require special cleanup operations. For example, if you destroy an array of characters maintained in the memory of an object, a string resource will be completely cleaned up. The CLR requires that all resources be allocated from the managed heap (managed heap). Objects that are not required by the application are automatically purged. So how does the managed heap know that an application no longer uses an object? "When the   process initializes, the CLR retains a contiguous address space, which initially has no physical memory space for the object. This address space is the managed heap. The managed heap also maintains a pointer, which I call nextobjptr. Points to the allocation position of the next object in the heap. At first, Nextobjptr is set to the base address of the reserved address space. The  IL directive newobj is used to create an object. Many languages provide a new operator that causes the compiler to generate a newobj instruction in the IL code of the method. The newobj directive causes the CLR to perform the following steps: #1, calculation typeThe number of bytes required for the field (extremely all base types). #2, plus the number of bytes required for the cost of the field. Each object has two cost fields: one is the type object pointer, and the other is a synchronous block index. #3, the CLR checks to see if the reserved zone can provide the number of bytes required to allocate the object, and commits the store if necessary (commit storage). If the managed heap has enough free space, the object is put in. The object is placed in the address pointed to by the nextobjptr pointer, and the bytes allocated for it are zeroed. Then, invoking the instance constructor of the type (passing NEXTOBJPTR for this parameter), the IL Directive newobj (or the C # new operator) returns the address of the object. Just before the address is returned, the value of the Nextobjptr pointer is added to the number of bytes occupied by the object, which gives a new value that points to the address of the next object when it is placed in the managed heap.    as a comparison, let's take a look at how the C runtime heap allocates memory, which allocates memory for an object to traverse a linked list of data structures, and once a large enough block is found, the block is split and the pointers in the linked list nodes are modified to ensure the integrity of the list. For the managed heap, the allocated object simply adds a value to a pointer-which is obviously much faster. In fact, allocating objects from the managed heap can be almost as fast as allocating memory from the thread stack! In addition, most heaps (C run-time heaps) allocate objects where they find free space. Therefore, if several objects are created consecutively, these objects are most likely to be dispersed, in the middle of a MB of address space. However, in the managed heap, successive allocations of objects ensure that they are contiguous in memory. The managed heap seems to be far superior to ordinary heaps in terms of simplicity and speed of implementation, such as the C run-time heap. The managed heap has these benefits because it makes a fairly bold assumption-that the address space and storage are infinite. This hypothesis is obviously not tenable, meaning that the managed heap must have some mechanism to allow it to make such assumptions. This mechanism is the garbage collector.   

CLR via C # Deep solution note Three-primitive type, reference type and value type | Type and member base | constants and Fields

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.