Zhonghui

每个不曾起舞的日子,都是对生命的辜负

User Tools

Site Tools


程序:csharp:内存管理

C#内存管理


new和引用类型

在C++中,也可以创建引用,但是默认情况下所有的变量包括自定义类都是值类型,在声明一个变量的时候,空间就分配好了,构造函数就执行完了,这是自动类型的变量。但是在C#中,有引用类型的存在,在创建引用类型的变量的时候,变量是创建好了,但是它引用的内存空间并没有分配好(就像在C++中声明了指针类型的变量一样),所以需要使用new创建真正的实例,使用new创建出来的内存,像是C++中的智能指针,当没有变量指向它的时候就会被回收了,C#也没有delete关键字,所以不需要担心内存泄漏的问题。

哪些是引用类型

自定义类都是引用类型,结构体都是值类型,其他的参见C#数据类型,引用类型就需要new。

using System;
 
class Data
{
    public int Number;
}
 
class MainClass
{
    static void Main(string[] args)
    {
        Data d1 = new Data();
        d1.Number = 1;
 
        Data d2 = d1; // d1 d2 是共享内存区的
        d2.Number = 2;
 
        Console.WriteLine(d1.Number); // 被修改为了2
 
        ChangeNumber(d1);
 
        Console.WriteLine(d1.Number); // 被修改为了3
    }
 
    static void ChangeNumber(Data d)
    {
        d.Number += 1; // 在函数内的修改也是在真正的内存区上进行的
    }
}

如何深拷贝/深复制

思路1: 手动复制成员变量

思路2: 序列化为字节流后,再复制,当然这就要求支持序列化

需要自己手写实现。类型需要是可以支持序列化的。

using System.Runtime.Serialization.Formatters.Binary;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
 
public static class DataHelper
{
    public static T DeepClone<T>(this T obj)
    {
        using (var ms = new MemoryStream())
        {
            var formatter = new BinaryFormatter();
            formatter.Serialize(ms, obj);
            ms.Position = 0;
 
            return (T)formatter.Deserialize(ms);
        }
    }
}
/var/www/DokuWikiStick/dokuwiki/data/pages/程序/csharp/内存管理.txt · Last modified: 2022/12/14 07:32 by zh