《Effective C#》系列之(三)——最小化内存泄露和资源占用

发布时间 2023-04-27 15:35:10作者: GroundSoft

在《Effective C#》这本书中,最小化资源泄漏是其中一章的内容。以下是该章节的一些核心建议,以及使用C#代码示例说明:

  1. 及时释放非托管资源:在使用非托管资源时,需要手动释放这些资源,以避免资源泄漏。例如:

    // 打开一个文件流并读取其中的数据
    using (var stream = new FileStream("file.txt", FileMode.Open))
    {
        var data = new byte[stream.Length];
        stream.Read(data, 0, data.Length);
        Console.WriteLine(Encoding.UTF8.GetString(data));
    }
    
  2. 及时释放托管资源:在使用托管资源时,也需要手动释放这些资源,以避免资源泄漏。例如:

    // 创建一个可释放的对象
    public class DisposableObject : IDisposable
    {
        private bool _disposed = false;
    
        // 实现IDisposable接口
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    
        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    // 释放托管资源
                }
    
                // 释放非托管资源
                _disposed = true;
            }
        }
    
        ~DisposableObject()
        {
            Dispose(false);
        }
    }
    
    // 使用可释放的对象
    using (var obj = new DisposableObject())
    {
        // do something with obj
    }
    
  3. 避免使用全局对象:全局对象容易造成资源泄漏,因此应该尽可能避免使用这种方式。例如:

    // 不要使用全局对象
    public static class GlobalObject
    {
        private static SomeResource _resource = null;
    
        public static SomeResource Resource
        {
            get
            {
                if (_resource == null)
                {
                    _resource = new SomeResource();
                }
                return _resource;
            }
        }
    }
    
    // 使用局部对象
    public void DoSomething()
    {
        using (var resource = new SomeResource())
        {
            // do something with resource
        }
    }
    
  4. 注意事件和委托的订阅和取消订阅:在使用事件和委托时,需要注意及时取消订阅,以避免资源泄漏。例如:

    // 订阅事件
    _someObject.SomeEvent += OnSomeEvent;
    
    // 取消订阅事件
    _someObject.SomeEvent -= OnSomeEvent;
    
  5. 避免循环引用:如果两个对象相互引用,可能会导致内存泄漏,因此需要注意避免这种情况。例如:

    // 避免循环引用
    public class A
    {
        private B _b;
    
        public A(B b)
        {
            _b = b;
        }
    }
    
    public class B
    {
        // ...
    }
    
    var b = new B();
    var a = new A(b);
    b = null; // 可以释放B对象
    a = null; // 也可以释放A对象
    

总之,以上这些建议都可以帮助程序员最小化资源泄漏,提高代码的可靠性和稳定性。