Ответ 1
Dispose
предназначен для освобождения "неуправляемых" ресурсов (например, сокетов, дескрипторов файлов, ручек растровых изображений и т.д.), и если он вызывается вне финализатора (что означает флаг disposing
, BTW), для удаляя другие объекты IDisposable, которые он удерживает, которые больше не являются полезными.
"Неуправляемые" ресурсы не управляются средой CLR (отсюда и название), и GC не возится с ними или не освобождает их самостоятельно; Отсутствует метод Dispose
(и код на самом деле его использует!), он будет полагаться на финализатор объекта для очистки. В конце концов финализатор запустится (если приложение здорово, а объект имеет финализатор), и если финализатор выполнит свою работу, то все полуфабрикаты... но это займет время сладкого времени - и если вы пока не хватит ручек, хорошо. Слишком плохо для этого другого потока/процесса/того, что им нужно.
Если вы Dispose
, то ресурсы немедленно освобождаются, а все работает лучше.
(Кстати, это не ограничивается EF, SQL Server или любой другой технологией. Шаблон одноразового использования найден в рамках .net-инфраструктуры, и считается хорошей практикой использовать его, когда у вас есть IDisposable, который больше не используется.)
Что касается того, почему IDisposable
реализуется до сих пор по дереву, а не просто реализует его в каждом конкретном случае... я не уверен на 100%. Но представьте, что вы пишете рамки. Считайте, что если бы все не было IDisposable, вам нужно было бы проверить - каждый раз, когда вы хотели избавиться от чего-то! - доступен ли объект, и Dispose
если это так. Если вы вместо этого реализуете IDisposable "на всякий случай", все упрощается - вы просто всегда распоряжаетесь. (Если объекту нет ничего для очистки, он просто не переопределяет Dispose
- в этом случае его родительский Dispose
вызывается и выполняет любую очистку, что может быть и ничего..) И это достаточно распространенный случай, когда контроллеры должны убирать вещи, даже если это не настоящая причина, в любом случае это имеет смысл.