2015-11-06 8 views
4

Так что в последнее время я работаю с одноразовым объектом, и мне было интересно, было бы ли это полезно для размещения объекта внутри функции? как между этими 2-мя функциями является использование .Dispose() действительно имеет значение внутри функции, так как все объекты в пределах функции исчезнет, ​​как только он закончитдействительно ли метод Dispose внутри функции?

void FOO() 
{ 
    var x= new DisposableObject(); 
    //stuff 
} 

void FOO() 
{ 
    using(var x= new DisposableObject()) 
    { 
     //stuff 
    } 
} 

ответ

2

Все объекты в функции исчезнет, ​​как только он закончит

объекты останутся, локальные ссылки будут равны нулю. Объекты будут «исчезать», когда сборщик мусора запускается и определяет, что они недоступны.

Прежде чем удаленный объект будет удален из памяти, его финализатор будет запущен (если он реализован), очистив все неуправляемые ресурсы.

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

Вы всегда должны называть метод Dispose, если это возможно.

Если вы хотите получить более подробную информацию о финализаторах, вы должны прочитать эти 2 статьи: part 1, part 2.

6

Вы должны всегда Dispose() объект, который нуждается в этом , Даже если объект является сборкой мусора, могут быть неуправляемые ресурсы, которые не освобождаются. Вызов Dispose() (или using, как в вашем втором примере) гарантирует, что объект может правильно освободить неуправляемые ресурсы, в которых он нуждается.

+0

Если класс реализован правильно, финализатор также очистит эти неуправляемые ресурсы. – i3arnon

+0

@ i3arnon Пожалуйста, посмотрите на это: http://stackoverflow.com/questions/3458177/are-net-finalizers-always-executed – itsme86

+3

@ i3arnon Не обязательно, а также вы даже не можете гарантировать, что финализатор будет работать для всех объекты. – Servy

2

Объекты не просто исчезают.

GC собирает экземпляры, на которые больше не ссылаются. Это может занять время, когда GC решает, когда запускать, и экземпляр не будет удален до его завершения.

Если это одноразовое устройство имеет неуправляемые ресурсы и выполнено правильно, ресурсы будут распределены финализатором, который является одним потоком.

Если вы согласны с тем, что экземпляр не был удален в течение некоторого времени, а финализатор не занят, тогда идите вперед. Но гораздо лучше, если вы избавитесь от него как можно скорее.

1

Установите точку останова в методе Dispose() и выполните эти тесты с помощью отладки. TestMethod1 не попадает в точку останова во время выполнения TestMethod2.

Как уже отмечалось, это связано с тем, как работает GC .Net Если вы собираетесь реализовать интерфейс IDiisposeable, вы, вероятно, захотите поместить свой класс в оператор using или вызвать .Dispose(), чтобы вы имеют более предсказуемое поведение приложения.

using System; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 

namespace UnitTestProject2 
{ 
    [TestClass] 
    public class UnitTest1 
    { 
     [TestMethod] 
     public void TestMethod1() 
     { 
      var disposable = new DisposableObject(); 
      disposable.DoSomething(); 
     } 

     [TestMethod] 
     public void TestMethod2() 
     { 
      using (var disposable = new DisposableObject()) 
      { 
       disposable.DoSomething(); 
      } 
     } 
    } 

    public class DisposableObject : IDisposable 
    { 
     public void Dispose() 
     { 
      // dispose here 
     } 

     public void DoSomething() 
     { 
      // do something here 
     } 
    } 
} 
+1

GC никогда не будет называть 'Dispose', it будет вызывать финализатор, который * должен * в свою очередь вызывать 'Dispose'. –