C# analysis of value types and reference types, heap memory and stack memory, shallow copy and deep copy

Abstract: Explain the concept, division and distinction of value types and reference types, as well as the different storage methods used in them-heap memory and stack memory.

Programming language: C#

Programming environment: Visual Studio 2019

Table of contents

The concept of value types and reference types

Common Value Types and Reference Types

The difference and connection between value type and reference type

the difference

connect

Heap and stack memory

concept

the difference

shallow copy and deep copy

concept

Implementation

example

summary 

each message


The concept of value types and reference types

        In C#, types are divided into two types—value types and reference types. Value type variables refer to variables that directly store data. Its instances are usually allocated on the stack (static allocation), while reference type variables hold data references. , its data is stored in the data heap, and its instances are allocated on the heap (dynamically allocated).

        Just looking at the concept may be abstract, let's use an example to illustrate.

int i = 10;//定义值类型——int型
int[] ii = { 1, 2, 3 };//定义引用类型——数组

//分别输出这两个变量
Console.WriteLine(i);
Console.WriteLine(ii);

        Execute the program, output

        It can be seen that for value types, its value is directly output, while for reference types, only its reference is output. Because the value type data is directly stored on the stack, and the reference type only stores the reference on the stack, and its data is stored in the heap, as shown in the figure.

 

Common Value Types and Reference Types

Common Value Types and Reference Types
value type basic data type int、float、double、char、bool等
enumerated type enum
structure struct
reference type kind Base class Object, string, custom class class
interface interface
array Arrays of various types

   

The difference and connection between value type and reference type

the difference

  • The storage methods in memory are different, which have been introduced in detail above.
  • The memory recovery method is different. The value type is stored on the stack and will be recycled immediately after use, while the reference type data is stored in the heap and will wait for garbage collection after use (GC garbage collector automatically recycles).
  • The value type contains its following data when it is declared, while the reference type only defines a pointer on the stack when it is declared, and it needs to be instantiated with new before opening up memory space in the heap. If you use a variable of uninstantiated reference type, a null pointer exception will occur because there is no corresponding memory space. Examples are as follows:

  • For value type assignment, it is equivalent to copying a new object with the same value, while for reference type assignment, it is equivalent to a reference to the original object, and changing its value will affect the original object. (This process belongs to shallow copy) The code example is as follows:

int i = 10;
int j = i;//i赋值给j,相当于复制一个同值新对象
j = 15;
Students student1 = new Students();//实例化学生1 张三 80
student1.Name = "张三";
student1.Score = 80;
Students student2 = student1;//学生1赋值给学生2,相当于student2拥有student1的引用
student2.Name = "李四"; 
student2.Score = 90;

//分别输出值类型i,j,发现i和j互不影响
Console.WriteLine(i);
Console.WriteLine(j);

//分别输出两个学生的信息,发现student1的信息被覆盖为student2
Console.WriteLine(student1.Name);
Console.WriteLine(student1.Score);
Console.WriteLine(student2.Name);
Console.WriteLine(student2.Score);

        Running the program, the output is

        It can be seen that the meanings of assignments of value types and reference types are different. The value type is to copy a new object, and the reference type is to copy a reference to the original object.

  • When used as parameters and return values ​​of functions, the rules are the same as above, the value type is the copy of the variable input parameters or return value, and the reference type is the reference to the variable copy input parameters or return value. 
  • Reference types can derive new types and support polymorphism, while value types are sealed and do not support polymorphism.

connect

  • Reference types can implement interfaces, and value types can implement interfaces with structures.
  • The reference type directly inherits from the System.Object class, and the value type directly inherits from the System.ValueTpye class, a subclass of Syetem.Object.

Heap and stack memory

concept

        When a C# program runs in the common language runtime (CLR), the memory is logically divided into two blocks, the stack and the heap. The heap is also called the managed heap, and the stack is also called the stack.

the difference

  • The stack space follows the last-in-first-out principle. When the top element of the stack is used up, it is released immediately; the heap space is like a warehouse, which will be searched and called by itself when needed, and needs to be cleaned by GC.
  • The stack space is relatively small, but reading data is fast; the heap space is relatively large, but reading data is slow.

shallow copy and deep copy

concept

        When making a shallow copy of an object, if it is a value type member, a new object equivalent to itself will be copied, if it is a reference type member, only its reference will be copied; when an object is deep copied, the reference type member will point to objects are also copied. When we want to completely copy a reference type object that has nothing to do with the original object, and the two are completely separated, we have to use deep copy.

Implementation

        For a shallow copy, assigning an object directly to a new object is a shallow copy, or using the object's MemberwiseClone() method to implement a shallow copy. For deep copy, Xiaobian introduces a more convenient method - deserialization method to realize deep copy, the code is as follows: (Note: T that calls this method needs to add [Serializable] in front to indicate that it can be serialized)

//反序列化深拷贝方法,T表示拷贝对象类,调用此方法需在T前加[Serializable]
public static T DeepCopyByBinary<T>(T obj)
{
    object retval;
    using (MemoryStream ms = new MemoryStream())
    {
        BinaryFormatter bf = new BinaryFormatter();
        bf.Serialize(ms, obj);
        ms.Seek(0, SeekOrigin.Begin);
        retval = bf.Deserialize(ms);
        ms.Close();
    }
    return (T)retval;
}

example

        Go directly to the code, where student2 is a shallow copy of student1, and student3 is a deep copy of student1.

Students student1 = new Students();//实例化学生1 张三 80
student1.Name = "张三";
student1.Score = 80;
Students student2 = student1;//学生1赋值给学生2,相当于浅拷贝
student2.Name = "李四"; 
student2.Score = 90;
Students student3 = DeepCopyByBinary(student1);//对学生1深拷贝,赋值给学生3
student3.Name = "王麻子";
student3.Score = 100;

//分别输出三个学生的信息
Console.WriteLine(student1.Name);
Console.WriteLine(student1.Score);
Console.WriteLine(student2.Name);
Console.WriteLine(student2.Score);
Console.WriteLine(student3.Name);
Console.WriteLine(student3.Score);

        The output is:

        It can be seen that after shallow copy, student2 is only a reference to student1; after deep copy, student3 and student1 are two independent objects.

summary 

        It is very important to understand the value type and reference type in C# programming, which will avoid the occurrence of many bugs; understanding the heap and stack under . Copy and deep copy allow us to correctly choose the appropriate copy method according to the copy needs.

each message

        A serious attitude can make things happen, and we can make things better. This is the secret that we cannot discard on the road of growth.

Guess you like

Origin blog.csdn.net/lucgh/article/details/130362522