Ответы на этот вопрос запутались более чем немного.
Название спрашивает об утилизации, но затем говорит, что они хотят немедленно вернуть память.
.Net является управляемым , что означает, что когда вы пишете .Net приложения, вам не нужно беспокоиться о памяти напрямую, цена того, что у вас нет прямого контроля над памятью.
.Net решает, когда лучше очистить и освободить память, а не вы, как кодер .Net.
Dispose
- это способ сообщить .Net, что вы покончили с чем-то, но на самом деле он не освободит память, пока не наступит наилучшее время для этого.
По сути .Net на самом деле собирает память обратно, когда это проще всего сделать - она очень хорошо решает, когда. Если вы не пишете что-то очень много памяти, вам обычно не нужно отменять это (это одна из причин, по которой игры еще не часто пишутся в .Net - им нужен полный контроль)
В .Net вы можете использовать GC.Collect()
, чтобы заставить его немедленно, но это почти всегда плохая практика. Если .Net еще не очистил его, это означает, что сейчас не самое подходящее время для этого.
GC.Collect()
подбирает объекты, которые .Net идентифицирует как выполненные. Если вы не удалили объект, который нуждается в этом, .Net может решить сохранить этот объект. Это означает, что GC.Collect()
эффективен, только если вы правильно внедрили свои одноразовые экземпляры.
GC.Collect()
является не заменой для правильного использования IDisposable.
Так что Распоряжение и память не связаны напрямую, но они не должны быть связаны. Правильная утилизация сделает ваши .Net приложения более эффективными и, следовательно, потребляет меньше памяти.
99% времени в .Net следующие рекомендации:
Правило 1: Если вы не имеете дела с неуправляемым или с тем, что реализует IDisposable
, тогда не беспокойтесь об утилизации.
Правило 2: Если у вас есть локальная переменная, реализующая IDisposable, убедитесь, что вы избавляетесь от нее в текущей области видимости:
//using is best practice
using( SqlConnection con = new SqlConnection("my con str" ) )
{
//do stuff
}
//this is what 'using' actually compiles to:
SqlConnection con = new SqlConnection("my con str" ) ;
try
{
//do stuff
}
finally
{
con.Dispose();
}
Правило 3: Если у класса есть свойство или переменная-член, которая реализует IDisposable, то этот класс должен также реализовать IDisposable. В методе Dispose этого класса вы также можете избавиться от своих свойств IDisposable:
//rather basic example
public sealed MyClass :
IDisposable
{
//this connection is disposable
public SqlConnection MyConnection { get; set; }
//make sure this gets rid of it too
public Dispose()
{
//if we still have a connection dispose it
if( MyConnection != null )
MyConnection.Dispose();
//note that the connection might have already been disposed
//always write disposals so that they can be called again
}
}
Это на самом деле не завершено, поэтому пример закрыт. Наследование классов может потребовать соблюдения следующего правила ...
Правило 4: Если класс использует неуправляемый ресурс, то реализуйте IDispose и добавьте финализатор.
.Net ничего не может сделать с неуправляемым ресурсом , так что теперь мы говорим о памяти. Если вы не очистите его, вы можете получить утечку памяти.
Метод Dispose должен работать как с управляемыми , так и неуправляемыми ресурсами.
Финализатор - это мера безопасности - он гарантирует, что если кто-то еще создаст и экземпляр вашего класса и не сможет его утилизировать, «опасные» неуправляемые ресурсы могут быть очищены с помощью .Net.
~MyClass()
{
//calls a protected method
//the false tells this method
//not to bother with managed
//resources
this.Dispose(false);
}
public void Dispose()
{
//calls the same method
//passed true to tell it to
//clean up managed and unmanaged
this.Dispose(true);
//as dispose has been correctly
//called we don't need the
//'backup' finaliser
GC.SuppressFinalize(this);
}
Наконец, перегрузка Dispose, принимающая логический флаг:
protected virtual void Dispose(bool disposing)
{
//check this hasn't been called already
//remember that Dispose can be called again
if (!disposed)
{
//this is passed true in the regular Dispose
if (disposing)
{
// Dispose managed resources here.
}
//both regular Dispose and the finaliser
//will hit this code
// Dispose unmanaged resources here.
}
disposed = true;
}
Обратите внимание, что как только все это будет создано, другой управляемый код, создающий экземпляр вашего класса, может просто обрабатывать его как любой другой IDisposable (правила 2 и 3).