2010-05-15 6 views
5

В C# можно создавать слабые ссылки на объекты, как описано здесь:Слабые ссылки и одноразовые предметы

WeakReference Class

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

Если я назначаю объект, который реализует IDisposable для слабой ссылки, будет Dispose вызываться, если слабая ссылка собирает объект?

+2

Что вы имеете в виду под «WeakReference» собирает свои объекты? это просто слабая ссылка, то есть объект, на который он указывает, может собираться сборщиком мусора. В этом случае все, что вы знаете о сборщике мусора, применяется ... – flq

+0

Как сказал Фрэнк, объект будет просто собран сборщиком мусора. Это, в свою очередь, вызовет финализатор, если у вас есть такой. Метод Dispose никогда не будет запущен. – Steffen

ответ

5

В общем, ответ на самом деле номер

Однако правильно реализован класс, который реализует IDisposable с использованием IDisposable pattern (hopefuly все классы .NET это сделать). Также будет реализовывать финализатор, который вызывается, когда объект собирает мусор и внутри финализатора, он будет звонить Dispose. Таким образом, для всех правильных реализаций IDisposable будет вызываться метод Dispose.

(Примечание: контрпример Фернандо не выполняет IDisposable правильно)

+2

Фактически, «стандартный» финализатор только вызывает «Dispose (bool)»; 'Dispose()' не вызывается, поэтому никакая очистка, которая зависит от управляемого кода (например, очистка базовых потоков файлов), не может быть выполнена. –

5

GC никогда не вызывает Dispose. Dispose должен вызываться по коду пользователя.

+1

Ваш дизайн может быть лучше обслуживается заменой 'WeakReference' на' RefCountDisposable' из библиотеки [Rx] (http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx). –

1

No. Проверить этот тест:

class Program { 
     static void Main(string[] args) { 
      Test test = new Test(); 
      Console.WriteLine(test.Disposable == null); 
      GC.Collect(); 
      Console.WriteLine(test.Disposable == null); 
      Console.ReadLine(); 
     } 
    } 

    public class Test { 
     private WeakReference disposable = new WeakReference(new WeakDisposable()); 
     public WeakDisposable Disposable { 
      get { return disposable.Target as WeakDisposable; } 
     } 
    } 

    public class WeakDisposable : IDisposable { 
     ~WeakDisposable() { 
      Console.WriteLine("Destructor"); 
     } 
     public void Dispose() { 
      Console.WriteLine("Dispose"); 
     } 
    } 

Выход:

False 
True 
Destructor 

Как вы можете видеть, исполнение никогда не попадает в метод Dispose.