Reference types and value types in C #

Source: Internet
Author: User

One, value types and reference types in C #

It is well known that there are two basic types in C #, each of which are value types and reference types, and each can be subdivided into the following types:

  1. What are value types and reference types
    • What is a value type:
      • Further studying the document, you will find that all structures are direct derived classes of abstract type System.ValueType, and System.ValueType itself is derived directly from System.Object. By definition, all value types must derive from System.ValueType, all enumerations derive from the System.Enum abstract class, and the latter derive from System.ValueType.
      • All value types are implicitly sealed (sealed) to prevent any other type from deriving from a value type.
    • What is a reference type:
      • All of the classes in C # are reference types, including interfaces.
  2. Differences and performance
    • Difference:
      • Value types are often referred to as lightweight types because, in most cases, instances of value types are allocated in the thread stack, so it is not controlled by garbage collection, alleviates the pressure in the managed heap, reduces the number of garbage collection applications, and improves performance.
      • All instances of the reference type are allocated on the managed heap, and the new operator in C # Returns a memory address pointing to the current object. So when you create a reference type instance, you have to consider the following questions:
        • The memory is allocated on the managed heap
        • Each object is allocated with additional members (type Object pointers, synchronized block indexes) that must be initialized
        • Other bytes in the object are always set to zero
        • A garbage collection operation may occur when an object is allocated (if there is not enough memory on the managed heap to allocate the object once)
    • Performance:
      • When designing an application, if all are application types, the performance of the application will be significantly reduced as this will increase the pressure on the managed heap and increase the number of garbage collections.
      • Although a value type is a lightweight type, if a large number of value types are used, it can also compromise the performance of your application (for example, the boxing and unboxing operations below, passing a large value type for an instance, or returning a large instance of a value type).
      • Because the value of a value type instance is itself, and the value of an instance of a reference type is a reference, if a variable of one value type is assigned to a variable of another value type, a verbatim copy is performed, and a variable of the reference type is assigned to a variable of another reference type, only the memory address needs to be copied. Therefore, you should avoid using value types when assigning large objects to a value. For example, the following code
        1  classSomref2     {3          Public intx;4     }5     structSomeval {6          Public intx;7     }8     classProgram {9         Static voidValuetypedemo () {TenSomref R1 =NewSomref ();//allocate on the heap OneSomeval V1 =NewSomeval ();//Allocate on Stack Ar1.x =5;//Lifting Hands -v1.x =5;//Modify on Stack -Somref r2 = R1;//Copy only references (pointers) theSomeval v2 = v1;//assigning and copying members on the stack -         } -}

  3. Common pitfalls
      • The reference type is assigned on the managed heap, and the value type is allocated on the thread stack: In fact, the first half of this statement is correct, the latter part is wrong. Because the value of a variable is stored at its declared location, if a variable of a value type is in a reference type, the value of the variable is always together with other data of the object of that reference type, that is, allocated on the heap. (only local variables (variables declared inside the method) and parameters of the method are on the stack)
      • The structure is a lightweight class: This error message is mainly because some people think that value types should not have methods or other meaningful behaviors-they should be used as simple data transfers, so many of you can't tell whether a datetime is a value type or a reference type.
      • The default object in C # is passed by reference: In fact, when invoking a method, the parameter value (a reference to the object) is passed in a worthwhile way, and if you want to pass it by reference, you can use the ref or out keyword.

Two, the value type of boxing and unpacking operations

1 int 5 ; 2 object o = i; 3 int j = (int) o;
4 Int16 y= (Int16) o;

    1. What is boxing and what is unpacking
      • What is boxing: the so-called boxing is the process of converting a value type into a reference type (for example, line 2nd of the above code), and in boxing you need to know what is going on inside the compiler:
        • Allocates memory in the managed heap, the amount of memory allocated is the amount of memory that is required for each field of the value type plus the two additional members (type object pointer, synchronous block index) of the object on the managed heap
        • A field of value type is copied into the newly allocated heap memory
        • Returns the address of the object, which is the reference to this object
      • What is boxing: the process of converting a boxed value type instance (at this point, which is already a reference type) to a value type (for example, line 3rd of the above code), note: Unpacking is not directly the packing process upside down, the cost of unpacking is much lower than boxing, unpacking is actually the process of acquiring a pointer. When a boxed instance is unpacking, the compiler does the following things internally:
        • A NullReferenceException exception is thrown when a variable that contains "instance reference to a boxed type" is null.
        • If the reference to the object is not a boxed instance of the expected value type, a InvalidCastException exception is thrown (for example, line 4th of the preceding code).
  1. Under what circumstances they occur, and how to avoid
  2. 1    Static voidMain (string[] args)2         {3             intv =5;4             Objecto =v;5v =123;6Console.WriteLine (v+","+(int) o);7}

    We have learned from the above analysis that boxing and unboxing/copy operations can have an adverse effect on the speed and memory consumption of the application (e.g., memory consumption, increase in garbage collection times, copy operations), so we should be aware of when the compiler generates code to automate these operations, and try to write the code, Try to avoid the case of automatic code generation.

    • Can you see from the code above how many boxing operations have been done? The answer is 3 times. What happened three times, let's take a look: The first object o=v, the second time the Console.WriteLine (v+ "," + (int) o) is executed, the V is boxed, then the O is unboxing and then the box is boxed. That is, the packing process is always in our casual time, so only we fully understand the internal mechanism of boxing, can effectively avoid boxing operations, thereby improving the performance of the application. So the following modifications to the above code can reduce the number of boxing times, thus improving performance:

      1  Static voidMain (string[] args)2         {3             intv =5;4             Objecto =v;5v =123;6Console.WriteLine (v.tostring () +","+ ((int) o). ToString ());//((int) o). The ToString () code itself has no meaning, just for demo boxing and unboxing operations7}
    • The following is a discussion of when the compiler will automatically generate code to complete these operations
      • When using non-generic collections: such as ArrayList, because these collections require objects that are object, if you add a value type object to the collection, a boxing operation is performed, and when you take a value, the unboxing operation is performed, so you should avoid using this non-generic collection in your application.
      • As you all know, System.Object is a base class of all types, and when you call a non-virtual method of type object, it is boxed (for example, the GetType method). When you call the virtual method of object, if your value type does not override the virtual method to also do boxing, you should override the virtual method inside the object when defining your own value type (for example, ToString)
      • A boxing operation occurs when a value type is converted to an interface type, because the interface type must contain a reference to an object on the heap.

Third, the appearance of generics (this section simply describes the role of generics in boxing and unboxing, refer to the next article for specific details about generics)

    • What generic type
      • Generics are a special mechanism provided by the CLR and programming languages and are provided in c#2.
    • What does it do to avoid boxing?
      • You need to specify the type to assemble when using generics, which reduces boxing operations, such as the following code
        1   Static voidMain (string[] args)2         {3ArrayList datelist =NewArrayList {4 DateTime.Now5             };6 7Ilist<datetime> Datet =NewList<datetime> { 8 DateTime.Now9             };Ten}

        When you use ArrayList, boxing takes place every time you add, while using list<datetime> does not carry out boxing, which improves the performance of your application.

    • Generic collections that are common in C #:

      queue<t>;

      stack<t>;

      list<t>;

      dictionary<tkey,tvalue>;

      hashset<t>;

      Before using these collections we have to understand how each set works (it's OK to do it yourself), to understand where each set fits, so you can write efficient code.

Iv. How to select classes and structs at design time

In the interview, we are often asked a question (there is another question, how to choose the abstract class and interface, next time I will talk about this problem), let's talk about how to choose the structure and class at design time

      • What is a structural body?
        • A struct is a special type of value, so it has the privilege of a value type (the instance is generally allocated on the thread stack) and the limit (cannot be derived, so there is no abstract and sealed, and the unboxed instance cannot be accessed by threads for synchronization).
      • Under what circumstances select a struct, and under what circumstances select the class
        • In most cases, you should select a class and consider selecting a struct unless the following conditions are met:
        • Type has primitive type behavior
        • Type does not need to inherit from any other type
        • Type is not derived from any other type
        • The instance of the type is small (approximately 16 bytes or smaller)
        • The instance of the type is large, but not passed as a parameter of the method, nor as the return value of the method.

All said that the program is a practice-oriented discipline, but also only familiar with the understanding of these things, in order to write good code in practice, there is no wrong or unreasonable places to welcome the discussion below;

 

Reference types and value types in C #

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.