Вы объединяете понятие избавления, которое в .NET означает «реализацию IDisposable
и, следовательно, Dispose ()
метод», и которое гарантирует, что неуправляемые ресурсы освобождаются, и концепция сбора мусора, которая обрабатывается средой выполнения и означает «освобождение памяти, выделенной объектам». Пока вы сохраняете ссылку на любой объект, сборщик мусора не будет к нему прикасаться - поэтому память, выделенная объектом, не освобождается до тех пор, пока это не произойдет.
Эти понятия легко спутать по двум причинам:
Во-первых, обычно рекомендуется работать с IDisposable
объектами с помощью оператора using
следующим образом:
using (IDisposable d = new MyDisposableObject ()) {
// do whatever you need d for
}
, который обеспечивает удаление d
при выходе из блока using
; но он также ограничивает область действия d
блоком, а это означает, что, как только исполняется блок, объект также может свободно собирать мусор (не обязательно, что это будет немедленно, но это ни здесь, ни их, поскольку ваш код дольше сохраняет ссылку на него). Таким образом, в этой (чрезвычайно распространенной и, вероятно, следует считать стандартной) идиоме, удаление происходит одновременно с удалением ссылок.
Во-вторых, хорошей практикой для классов, которые напрямую обращаются к неуправляемым ресурсам, является реализация финализатора, который вызывает Dispose ()
. Финализаторы запускаются, когда объект подвергается сборке мусора, поэтому вы можете быть уверены, что никогда не оставите висячую утечку на неуправляемом ресурсе, но если объект никогда не удаляется должным образом, вы оставляете решение о том, когда освобождать неуправляемые ресурсы. строго в руках среды выполнения, которая решает, когда выполнять сборку мусора только на основе нехватки памяти, и не знает и не интересуется количеством или типом ссылок на неуправляемые ресурсы. Таким образом, в этом случае сборка мусора объекта приводит к удалению неуправляемых ресурсов.
В случае, когда вы явно вызываете Dispose ()
для метода, например, в своем вопросе (при условии, конечно, что Object1
реализует IDisposable
), вы все равно сохраняете ссылку на obj
, и, как следствие, из этого могут получить доступ ко всем его свойствам и методам. Конечно, совершенно разумно, чтобы эти методы или свойства требовали неуправляемого ресурса, который вы уже утилизировали, и в этом случае может быть выброшен System.ObjectDisposedException
, или же авторы Object1
решили использовать этот случай, но для них также вполне разумно функционировать, как ожидается, если им не требуются ресурсы, которые вы освободили.
В качестве примера посмотрите на System.IO.FileStream
. Как только вы избавитесь от него, такие операции, как ReadByte ()
, выдают исключение, поскольку очевидно, что нет доступа к файлу для чтения, но вызов свойства CanRead
просто возвращает false
, что является допустимым и ожидаемым. (Например, MemoryStream
может даже получить доступ к данным после вызова Dispose ()
, поскольку (текущая) реализация использует буфер, управляемый средой выполнения, а не что-то вроде дескриптора ядра).