C # Basic Series 1---in-depth understanding of value types and reference types

Source: Internet
Author: User
Tags garbage collection

"Meal": originated from their own just stepping into the chaos of the monkey picked up, the sense of self is not a general dish, hence the name "meal", in their own mutual encouragement.

Unconsciously has been stepping into the pit has been more than more than 10 years, for C # Some of their own knowledge, write to crave the same kind of attack on their own is a decade of the itch of a summary. I heard there are many people who like to have a beautiful picture.

Basic concepts

The CLR supports two types: value types and reference types. Interviewing a lot of students 5 years or so, there are a lot of value types and reference types of basic concepts are not answered, is the current C # developer base so weak? Or do we all pay no attention to the foundation? This is a casual blog can be a basic primer.

Reference type

What types are reference types? in fact, a type that can be called a "class" is a reference type . Reference types are always allocated from the managed heap , and the usual syntax is new XX (). The new operator of C # Returns a pointer to an object-that is, a reference to the memory address of the object's data. The passing of a reference type is actually a pointer to the object (aspecial type of string ), so performance is higher than the value type in a particular scenario. A reference type defaults to NULL when it is created, meaning that the current variable does not point to a valid object, which is the exception that we often encounter "object references are not set to an instance of an object."

Value type

Because reference-type variables require one-time allocation of heap memory, which can put a lot of pressure on the GC, the CLR provides a lightweight type of "value type". Value types are typically assigned on line Stacks . (Note: Value types can be embedded in a reference object) a value type variable actually contains the value of the value type instance, so it does not have a pointer to a reference type ( guess the value type needs no type Object pointer?). )

Same points and different points of the same point
    1. Both the value type and the reference type are System.Object subclasses
    2. Both value types and reference types can inherit interfaces. (Many people think value types cannot inherit interfaces)

       interface Itest {     void test(); } struct TestStruct : Itest {     public void test()     {         throw new NotImplementedException();     } }
Different points
    1. Value types are allocated on the stack, and reference types are allocated on the managed heap. One point to note here is that if a property in a reference type is a value type, the property of that value type is allocated on the managed heap .
    2. All value types are implicitly sealed (sealed), for example: you cannot inherit int to construct your own type.
    3. Each assignment of a value type performs a verbatim copy of a segment, so if it is frequently assigned a performance stress, the assignment of a reference type is just a pointer pass, and in fact a new pointer instance is generated.
    4. Reference types have additional type object pointers and synchronous block indexes, and value types are not. So we usually make lock -locked objects impossible to be value types because value types do not have synchronized block indexes

Performance

Some students say that value types have higher performance than reference types, so why not use value types? The same is true for reference types. Everything has two sides, only the right type, no universal type.

    1. Value type: The "lightweight type" in the so-called. NET Framework, why is it a "lightweight", which is directly related to his memory allocation, because value types are allocated on the stack, so there is no pressure on the GC outside of the GC's control. Can it be used casually? Of course not, for example: What happens when I customize a struct type as a parameter of a method? The assignment of the full field occurs every time it is called, which is unacceptable, which is also a typical value type.
    2. Reference type: The reference type is allocated in the heap, so it affects the GC, and if the reference type is frequently initialized, the pressure on the GC is significant, because each allocation is likely to force a garbage collection operation. Also, mention that the occupied memory of a reference type, not all attributes/fields, and every object allocated on the heap has some extra members that must be initialized. (Type object pointer and memory block index).
    3. Packing and unpacking: the so-called boxing is the process of converting a value type to a reference type. Unpacking is the opposite (just conceptually opposite, the actual compiler operates differently). Some students say packing and unpacking affect the performance, that is the boxing effect or unpacking it or all affect it?
      1. What happened to the boxing process:
        1. 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
        2. A field of value type is copied into the newly allocated heap memory
        3. Returns the address of the object, which is the reference to this object
      2. What happened to unpacking the box:
        1. Gets a pointer to an instance of a value type that has been boxed
        2. Copy the acquired value to the stack

So boxing is more cost-intensive, and it is possible to trigger a GC operation, and unpacking is just a process that takes a pointer and consumes less resources than boxing. Note: an object can only be restored to a previously unboxed type after unpacking , for example: You cannot pack the Int32 type to revert to the Int16 type. So when the interview can and the interviewer outfit B ~ ~

The test example value type reference type initializes the time of N consumption respectively, the code is as follows
static void Main(string[] args)    {        Console.WriteLine("test start");        int totalCount = 10000000;        Stopwatch sw = new Stopwatch();        sw.Start();        for (int i = 0; i < totalCount; i++)        {            TestRef temp = new TestRef() { Id = i, Name = "test" };        }        sw.Stop();        Console.WriteLine($"引用类型耗时:{sw.ElapsedMilliseconds}");        sw.Reset();        sw.Start();        for (int i = 0; i < totalCount; i++)        {            TestVal temp = new TestVal() { Id = i, Name = "test" };        }        sw.Stop();        Console.WriteLine($"值类型耗时:{sw.ElapsedMilliseconds}");        Console.Read();    }    class TestRef    {        public int Id { get; set; }        public string Name { get; set; }    }    struct TestVal    {        public int Id { get; set; }        public string Name { get; set; }    }

Operation Result:

引用类型耗时:205值类型耗时:152

It can be seen that the initialization speed value type is better than the reference type, or that the reference type caused the GC.

To pass as a method parameter, the code is as follows:
static void Main (string[] args) {Console.WriteLine ("Test Start");        Long totalcount = 1000000000;        Stopwatch SW = new Stopwatch (); Sw.        Start (); Testref tempref = new Testref () {Id = 1, Name = "Test", name2= "R3rewfdsafdsa", name3= "Fsrewfdsafdsafdsa", name4= "Fdafdas        Fdsafdsa ", name5=" 432tretsfds ", name6=" FDSAFDASFDASFD "};        for (int i = 0; i < TotalCount; i++) {testr (tempref); } SW.        Stop (); Console.WriteLine ($ "Reference type is time consuming: {SW.        Elapsedmilliseconds} "); Sw.        Reset (); Sw.        Start (); TestVal tempval = new TestVal () {Id = 1, Name = "Test", Name2 = "R3rewfdsafdsa", Name3 = "Fsrewfdsafdsafdsa", Name4 = "FD        Afdasfdsafdsa ", Name5 =" 432tretsfds ", Name6 =" FDSAFDASFDASFD "};        for (int i = 0; i < TotalCount; i++) {Testv (tempval); } SW.        Stop (); Console.WriteLine ($ "value type is time consuming: {SW.        Elapsedmilliseconds} ");    Console.read (); } static void Testr (Testref r) {        Return    } static void Testv (TestVal v) {return;        } class Testref {public int Id {get; set;}        public string Name {get; set;}        public string Name2 {get; set;}        public string Name3 {get; set;}        public string Name4 {get; set;}        public string Name5 {get; set;}    public string Name6 {get; set;}        } struct TestVal {public int Id {get; set;}        public string Name {get; set;}        public string Name2 {get; set;}        public string Name3 {get; set;}        public string Name4 {get; set;}        public string Name5 {get; set;}    public string Name6 {get; set;} }

Operation Result:

引用类型耗时:4437值类型耗时:5226

It can be seen that in normal cases, there is little difference in time as a parameter value type and reference type, but if the value type's instance attributes are more large, the gap falls further.

非正式环境测试用例,结果仅供参考
Application Scenarios

Not only is the interview time often ask the application scenario this question, is oneself usually writes the procedure also should be clear. Most scenarios are reference types when designing a program, but value types may be more appropriate if you meet the following criteria:

    1. Type does not derive any other type, that is, there is no possibility of inheritance
    2. Type does not need to inherit other types
    3. Instances of type are small and are not used as method parameters and are not frequently assigned
    4. You will never use a notification when the type is released, because the reference type can use the destructor to get the notification when it is released.
    5. If your type instance does not change in value or can be considered readonly, the value type may be preferred.

      Other
    6. All value types are derived from System.ValueType, System.ValueType inherit System.Object, but System.ValueType overrides the Equals and GetHashCode methods, In fact, here is the actual and reference type of Split line.
    7. Collection performance like ArrayList is very worrying because value types have boxing unboxing operations. So C # 2.0 appears generics such as: List ..... To ensure the type of safety, but also to avoid the unboxing, because it is not my definition of the type, you TMD even the compiler that the level can not pass ha ha ~ ~ ~ ~

By the way, long time do not write blog, style Real take a moment, ah, and then simply write Markdown format, please forgive us!!

请尊重一个猿的辛苦,请标明出处 ^ ~ ^  。部分图片来源于网络,如果侵权请及时联系我。让我们一起进步吧

A public number that goes beyond the content of the IT community, welcome attention, and exchange more it knowledge. There will be surprises when you are uncertain.

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.