2008-09-29 6 views
224

В .NET, при каких обстоятельствах следует использовать GC.SuppressFinalize()?Когда следует использовать GC.SuppressFinalize()?

Какая польза от этого метода дает мне?

+0

Я видел несколько вопросов о финализаторах и IDisposable, StackOverflow также должен иметь что-то о GC.SupressFinalize и слабых ссылках – 2008-09-29 22:42:53

+0

Я не думаю, что слабые ссылки многого сделать что-нибудь о финализаторах - может быть, вы должны размещать более прямой вопрос о них. – 2008-09-30 15:41:47

+0

Yerp Я имел в виду опубликовать отдельный вопрос о слабых ссылках, все это может связываться вместе при создании пулов объектов. Также я должен задать вопрос об оживлении объекта ala ReRegisterForFinalize – 2008-09-30 22:50:19

ответ

243

SuppressFinalize следует вызывать только классом с финализатором. Он информирует сборщика мусора (GC) о том, что объект this был полностью очищен.

Рекомендуемый шаблон IDisposable, когда у вас есть финализатор:

public class MyClass : IDisposable 
{ 
    private bool disposed = false; 

    protected virtual void Dispose(bool disposing) 
    { 
     if (!disposed) 
     { 
      if (disposing) 
      { 
       // called via myClass.Dispose(). 
       // OK to use any private object references 
      } 
      // Release unmanaged resources. 
      // Set large fields to null.     
      disposed = true; 
     } 
    } 

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

    ~MyClass() // the finalizer 
    { 
     Dispose(false); 
    } 
} 

Обычно CLR поддерживает вкладки на объектах с финализации, когда они создаются (делая их более дорогими для создания). SuppressFinalize сообщает GC, что объект был очищен должным образом и не нужно идти в очередь финализатора. Это похоже на деструктор C++, но не действует ни на что.

Оптимизация SuppressFinalize не является тривиальной, так как ваши объекты могут долго ждать в очереди финализатора. Не поддавайтесь соблазну вызвать SuppressFinalize на других объектах, которые вас увидят. Это серьезный недостаток, ожидаемый.

Руководства по проектированию сообщают нам, что финализатор не нужен, если ваш объект реализует IDisposable, но если у вас есть финализатор, вы должны реализовать IDisposable, чтобы разрешить детерминированную очистку вашего класса.

В большинстве случаев вы должны уйти с IDisposable для очистки ресурсов. Вам нужно только финализировать, когда ваш объект держится на неуправляемых ресурсах, и вам нужно гарантировать, что эти ресурсы будут очищены.

Примечание. Иногда кодеры добавят финализатор для отладки сборников своих собственных классов IDisposable, чтобы проверить, что этот код правильно разместил свой IDisposable-объект.

public void Dispose() // Implement IDisposable 
    { 
     Dispose(true); 
    #if DEBUG 
     GC.SuppressFinalize(this); 
    #endif 
    } 

    #if DEBUG 
    ~MyClass() // the finalizer 
    { 
     Dispose(false); 
    } 
    #endif 
29

вы сообщаете системе, что все работы были бы сделано в финализаторе уже сделано, поэтому финализации не нужно называть. Из .NET Docs:

объекты, которые реализуют интерфейс IDisposable может вызвать этот метод из метод IDisposable.Dispose в предотвратить сборщик мусора из вызывающего Object.Finalize на объект, который не требует Это.

В общем, любой метод Dispose() должен иметь возможность вызвать GC.SupressFinalize(), поскольку он должен очищать все, что было бы очищено в финализаторе.

SupressFinalize - это что-то, что обеспечивает оптимизацию, которая позволяет системе не беспокоиться о том, чтобы связать объект с потоком финализатора. Правильно написанный Dispose()/finalizer должен работать правильно с вызовом GC или без него. SupressFinalize().