2. string 在内存中是连续分配的,是一个数组, 数组的特点就是 查询块,增删慢,改动Array导致所有数组成员地址变动,成本高 而string又是在程序中经常变动的 ,所有 clr中对 string 这种引用类型做特殊处理, 使用字面量声明 string时, 会先到string驻留池中查找 要声明的值有无,有直接把 池中实例地址返回 赋值给变量 .无则 新增
3. CLR的内存分配
4. GC 相关
析构函数 类型名称价加个~ 单独的处理,把这些对象放入一个队列单独处理,但是不知道什么时候去调用后析构函数
主要是用来释放非托管资源
析构函数 与 Dispose() 都是用来非托管资源的 , 有什么区别
被动 主动释放
如下图代码, using 代码块结束后, 会调用student的 dispose方法
如果 项目中需要封装一些 非托管资源供别人调用 , 实现Idispose接口的 一般逻辑是: 参考下 Student 类的实现
1. 假如别人用我的代码时 使用了dispose() 方法来释放资源, 手动调用 GC.SuppressFinalize(this) 告诉GC 不需要你来释放了 (提供主动释放方式,最快释放非托管资源)
2. 如果使用我代码的 没调用 dispose() , Student中的 析构函数 确保该资源能被 GC 回收 (保底)
public class People : IDisposable { public string Remark { get; set; } public virtual void Dispose() { MyLog.Log($"执行{this.GetType().Name}Dispose"); } } public class Student : People, IDisposable { public int Id { get; set; } public string Name { get; set; } public Class Class { get; set; } public override void Dispose()//提供主动释放方式 { base.Dispose();//把我引用的其他东西给清理掉 if (this.Class != null) { this.Class.Dispose(); } //通知垃圾回收机制不再调用终结器(析构器) GC.SuppressFinalize(this); MyLog.Log($"执行{this.GetType().Name}Dispose"); } public void Study() { Console.WriteLine("跟着Eleven老师学习.Net高级开发"); } ~Student()//保证垃圾回收时 一定会把非托管资源释放 { MyLog.Log($"执行{this.GetType().Name}Dispose"); } } public class Class : IDisposable { public int ClassId { get; set; } public string ClassName { get; set; } //~Class() //{ // MyLog.Log($"执行{this.GetType().Name}Dispose"); //} public void Dispose() { MyLog.Log($"执行{this.GetType().Name}Dispose"); } }