2014-01-13 7 views
0

Я надеюсь, что правильно знаю свои факты, если не поправлю меня.Почему вызов CLR Dispose автоматически

1) Вы используете Dispose для очистки неуправляемых ресурсов, что означает отсутствие сбора мусора для них.

2) Значение типа сохраняются в стеке, ссылочные типы, хранятся в куче и указатели ссылаться на типы хранятся в стеке (на самом деле не уверен насчет этого, но я думаю, что это правильно)

3) Финилеры вызывают сборщик мусора.

4) Сбор мусора вызывается CLR, а не пользователем (хотя он и может) для ссылочных типов, но типы значений уничтожаются (извините не удалось найти лучшего слова), когда они выходят за рамки

Я знаю об операторе using и способе работы, но я думаю, что было бы намного проще, если бы CLR вызывал Dispose для пользователя.

Итак, мой вопрос: «Если указатели на ссылочные типы хранятся в стеке, компилятор и среда CLR знают, когда объект выходит из области действия. Почему компилятор не генерирует какой-то IL-код, который вызывает Dispose, или почему CLR не делает этого, как это делают для финилеров и деструкторов ».

Извините, если мой вопрос не ясен, я с удовольствием обновляю его с любой другой информацией, в которой вы нуждаетесь. Спасибо.

+1

'Dispose' - это просто программирование _pattern_, которое хорошо поддерживается языком. Объекты не располагаются автоматически, так как целью было дать разработчику возможность распоряжаться ими явным и детерминированным образом. Если у вас возникли проблемы с этим, я предлагаю использовать инструкцию '' using' (http://msdn.microsoft.com/en-us/library/yh598w02.aspx). «Типы значений, хранящиеся в стеке» - это заблуждение и упрощение, реальность - [бит более тонкий] (http://blogs.msdn.com/b/ericlippert/archive/2009/04/27/the-stack -is-an-implementation-detail.aspx) –

+0

Обязательная литература относительно правильного способа реализации IDisposable: http://stackoverflow.com/a/538238/1288449 –

ответ

4

Вот проблема:

Если указатели на ссылочные типы, хранятся в стеке компилятор и CLR, знаете, когда объект выходит из области видимости

Это упрощение. У вас могут быть частные поля, которые являются одноразовыми. Они не будут храниться в стеке, и CLR не может знать, когда объект больше не используется, кроме использования Мусора. И, конечно же, Garbage Collection уже предоставляет механизм - финализатор, через который вы можете распоряжаться неуправляемыми ресурсами.

+0

Я согласен с тем, что то, что я сказал, является упрощением. Но когда GC происходит, он освобождает всю память от всех осиротевших объектов, поэтому CLR все еще должна знать, какие объекты больше не ссылаются. И финализаторы называются во второй коллекции GC по другой теме из того, что я знаю. В любом случае, я думаю, что это нормально. Не могли бы вы предоставить ссылку на некоторую документацию, которая показывает, как GC определяет, ссылается ли объект или нет. – trebor

+0

@toby Это может помочь: http://msdn.microsoft.com/en-us/library/ee787088%28v=vs.110%29.aspx Среда CLR определяет, на что ссылаются следующие цепочки указателей из «корней». –

2

Классы могут быть записаны, поэтому неуправляемые ресурсы очищаются только финализаторами, без использования Dispose. В этом случае GC очистит эти ресурсы «в какой-то момент» после того, как они больше не будут использоваться.

Однако в некоторых случаях, если эти ресурсы требуются, до тех пор, пока в будущем не будет произвольной точки. Например, если вы открываете дескриптор системного файла, другие приложения могут не открывать файл до тех пор, пока дескриптор не будет закрыт. Предоставляя код приложения для создания и вызова метода Dispose, приложение может детерминистически очистить неуправляемые ресурсы, гарантируя, что система не войдет в состояние, просто ожидающее, что GC будет запущен «когда-нибудь».

0

кода ссылки

void Blah(Thing Boz) 
{ 
    DisposableThing Foo = new DisposableThing(); 
    Boz.SomeMethod(Foo); 
} 

компилятор не будет иметь никаких проблем с определением того, что после выхода метода, ссылка Foo больше не потребуются.Если бы в то время не было никакой другой ссылки нигде во вселенной на DisposableThing, идентифицированной этой ссылкой, тогда DisposableThing должен иметь свой метод Dispose, который был вызван до его отказа. Проблема в том, что компилятор не знает, может ли SomeMethod сохранить ссылку на этот объект где-то в другом месте.

В подавляющем большинстве случаев, когда создается объект IDisposable, он будет передан в методы, подробности которых компилятор ничего не знает. Следовательно, компилятор не знает, будет ли конкретная ссылка на объект только ссылкой на объект в момент его выхода из области видимости.

Если метод был написан как:

void Blah(Thing Boz) 
{ 
    using (DisposableThing Foo = new DisposableThing()) 
    { 
     Boz.SomeMethod(Foo); 
    } 
} 

, которые инструктируют компилятор для вызова Dispose на вновь созданный объект после того, как Boz.SomeMethod() возвращается. Компилятор не попытается выяснить, мог ли Boz.SomeMethod() сохранить ссылку - оператор using вызовет Dispose независимо.

Смежные вопросы