2010-12-06 5 views

ответ

7

Реализовать IDisposable и очистить ваши неуправляемые ресурсы путем вызова Dispose(), предпочтительно поместить вызов Dispose в finally заявлении, так что вы очистки ресурсов даже в случае исключения.

C# имеет ключевое слово using, которое можно использовать, чтобы удостовериться, что вызывается метод Dispose, даже если выбрано исключение.

EDIT: Включенный вызов GC.SuppressFinalize и реализации финализатора в ответ Ран

class A : IDisposable 
{ 
    private bool _disposed; 

    ~A() 
    { 
     this.Dispose(false); 
    } 

    public void Dispose() 
    { 
     this.Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     if (!_disposed) 
     { 
      if (disposing) 
      { 
       // dispose managed resources 
      } 

      // clean up unmanaged resources 

      _disposed = true; 
     } 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     using (var someInstance = new A()) 
     { 
      // do some things with the class. 
      // once the using block completes, Dispose 
      // someInstance.Dispose() will automatically 
      // be called 
     } 
    } 
} 
+0

Я не думаю, что Финализатор необходим в ситуации ОП. См. Мой ответ для получения дополнительной информации .... – SpeksETC 2010-12-06 10:37:49

4

Использование IDisposable не может быть достаточно, потому что она опирается на пользователя запоминание вызвать Dispose или использовать using и т.д.

Для полного решения, объедините IDisposable и финализатор. Как это:

Edit: Сделаны некоторые корректировки в методе Dispose на основе SpeksETC комментарий «s.

class MyClass : IDisposable 
{ 
    ~MyClass() 
    { 
     Dispose(false); 
    } 

    public void Dispose() 
    { 
     GC.SupressFinalize(); 
     Dispose(true); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     if (!disposing) 
     { 
      // clear unmanaged resources here (can only be called once) 
      ... 
     } 

     // dispose called explicitly by the user, clean up managed resources here 
     ... 
    } 
} 

Это гарантирует, что местные ресурсы всегда будут очищены, даже если пользователь забывает позвонить Dispose, в то же время позволяя пользователю очистить ресурсы рано.

if внутри Dispose реализация необходима, потому что, если этот класс находится на стадии завершения, вы не можете назвать Dispose на своих членов, потому что они, возможно, были GC'ed уже.

+0

+1: Хорошая работа, связанная с финализатором. По какой-то причине я подумал, что Microsoft начала обескураживать практику. – 2010-12-06 08:44:55

+0

Финализаторы действительно имеют штраф за производительность, но я думаю, что это применимо только в том случае, если на самом деле вызывается финализатор (из-за накладных расходов GC, управляющих окончательной очередью и т. Д.). Таким образом, в вашем собственном приложении вы всегда должны утилизировать объекты, если сможете. Однако при написании библиотеки вы можете защитить своих пользователей, которые могут игнорировать вызов Dispose. Для них удар производительности будет лучше, чем утечка памяти ... – Ran 2010-12-06 08:58:22

1

Я думаю, что это очень важно отметить, что B является удалось ресурс, который только содержит неуправляемых ресурсов.

Поэтому A должен реализовывать IDisposable и удалять B в своем методе Dispose(), но не нуждается в финализаторе, так как у него нет неуправляемых ресурсов для очистки - финализатор должен быть реализован внутри самого B. Даже если вы реализовали финализации было бы назвать Dispose, который выглядел так:

protected virtual void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      // dispose called explicitly by the user, clean up managed resources here 
      b.Dispose() 
     } 

     // no unmanaged resources to clean up so do nothing which makes Finalizer unneccesary 
     ... 
    } 
0

SpeksEtc является правильным в том, что если B содержит неуправляемые ресурсы, то B должен гарантировать, что нет никаких утечек не A.

Но что являются неуправляемыми ресурсами и поможет ли класс SafeHandle? Тогда B будет содержать SafeHandle, который будет содержать неуправляемый ресурс, и вам не нужно будет беспокоиться об этом.

Смежные вопросы