Когда мне нужно управлять управляемыми ресурсами?
Я смотрю на стандартный шаблон Dispose, и мне просто интересно, что мне нужно написать для свободных управляемых ресурсов? Если эти ресурсы уже "управляются", то, конечно, мне не нужно ничего делать.
Если это так, и мой класс не содержит никаких неуправляемых ресурсов (следовательно, нет необходимости для его завершения GC), тогда мне нужно только подавить финализацию в моем методе Dispose?:-
public void Dispose()
{
GC.SuppressFinalize(this);
}
Итак, предположим, что это мой класс:
public sealed class MyClass : IDisposable
{
IList<MyObject> objects; // MyObject doesn't hold any unmanaged resource
private bool _disposed;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!_disposed)
{
// do I need to set the list to null and
// call Dispose on each item in the list?
if (disposing)
{
foreach (var o in objects)
o.Dispose();
objects = null;
}
}
_disposed = true;
}
~MyClass()
{
Dispose(false);
}
}
Нужно ли мне на самом деле освобождать управляемые ресурсы здесь?
Спасибо,
3 ответа
Если ваш класс содержит какие-либо IDisposable
экземпляры, вы используете управляемые ресурсы и, следовательно, вы должны реализовать IDisposable
чтобы позволить пользователям распоряжаться ресурсами. Ваш Dispose
метод должен вызывать Dispose
на управляемых ресурсах.
Что касается освобождения управляемой памяти, вам не нужно ничего делать. Это обрабатывается GC, но это единственная часть очистки, которая обрабатывается GC. Управляемые и неуправляемые ресурсы должны быть очищены Dispose
и / или финализаторы.
Если вы не используете какие-либо управляемые или неуправляемые ресурсы, нет необходимости реализовывать ни IDisposable
ни финализатор. Реализация финализатора фактически повлияет на производительность вашего типа, поэтому не используйте его, если он вам не нужен.
Вы должны утилизировать любой из управляемых объектов, которые реализуют IDisposable
,
Вы не сможете позвонить Dispose
на объектах, которые не реализуют IDisposable
так что вам нужно проверить это. (Очевидно, если все возможные экземпляры / потомки MyObject
всегда будет реализовывать IDisposable
тогда вам не понадобится эта проверка.)
Там нет необходимости устанавливать сам список null
,
В общем случае, я бы, вероятно, переписал цикл, чтобы он выглядел примерно так:
if (disposing)
{
foreach (var o in objects)
{
var d = o as IDisposable;
if (d != null) d.Dispose();
}
}
(Кстати, если ваш класс на самом деле не содержит IDisposable
объекты или неуправляемые ресурсы, то вам, вероятно, не нужно реализовывать IDisposable
или финализатор вообще.)
Есть две причины для реализации IDisposable:
1. Освободить ресурсы под управлением ООН. Этот случай ОЧЕНЬ редок, но, к сожалению, это то, о чем много говорится в документе. Речь идет о том, ЧТО освободить - т.е. избежать утечки ресурсов / памяти.
2. Освободить управляемый ресурс. Это распространено - речь идет не о том, чтобы гарантировать, что освобождается (потому что управляемые ресурсы всегда будут освобождаться в какой-то момент GC), а о том, КОГДА вещи освобождаются. Т.е. речь идет о предоставлении пользователю вашего объекта контроля над тем, КОГДА он освобождает управляемые ресурсы (т. Е. Когда закрывает сокеты, файлы и т. Д.), Чтобы другие вещи могли получить к ним доступ.
В вашем случае вы можете воспользоваться следующим минимальным удалением, если никакой производный класс не добавляет управляемые ресурсы:
public virtual void Dispose() {
foreach (var o in objects) {
var d = o as IDisposable;
if (d != null) d.Dispose();
}
}