TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.77K subscribers
Post #973 1.37K
День семьсот девяносто первый. #ЗаметкиНаПолях
Мои любимые ошибки с IDisposable. 3/3
Начало
Продолжение

4. Чрезмерная очистка
Во многих случаях мы передаём экземпляр IDisposable между методами или в конструкторы. Возникает вопрос: я должен отвечать за вызов Dispose или это сделает кто-то другой? Когда мы вызываем Dispose из неправильного места, мы получаем незаметные, трудно поддающиеся диагностике ошибки.

Совет на этот случай: если вы вызываете new, вы должны вызывать и Dispose. Если вы не вызывали new, вы не обязаны вызывать Dispose.

Рассмотрим эту функцию:
void Save(IDbConnection conn) {
using(conn) {
//…
}
}
Разработчик пытается поступить правильно и очистить ресурсы после использования. Но теперь вызов Save имеет побочный эффект закрытия соединения. Это может привести к ошибке в другом месте:
using(var cn = new SqlConnection("…")) {
Save(cn);
Update(cn); // ошибка
}
Мы получим исключение в Update, потому что функция Save закрыла наше соединение. Эта ошибка может быть довольно коварной: исключение будет выброшено из Update, поэтому поиск ошибки начнётся не в том месте. В зависимости от размера кодовой базы может потребоваться много времени, чтобы обнаружить, что обновление завершается ошибкой только при вызове после сохранения. Эта ошибка может тихо жить в кодовой базе в течение многих лет и проявиться, когда кто-то добавит вызов Update.

Эта ошибка также может быть выражена объектно-ориентированным образом, и отладка становится ещё более мутной, когда мы получаем наш IDisposable через внедрение зависимости (DI):
public class Saver : IDisposable {
readonly IDbConnection _conn;

public Saver(IDbConnection conn) {
_conn = conn;
}
public void Save() {…}
public void Dispose() {
_conn.Dispose();
}
}
Опять же, разработчик пытается поступить правильно и очистить ресурсы после использования, но мы вводим неожиданные побочные эффекты в IDbConnection. Можно написать такой правильный код:
using(var cn = new SqlConnection("…")) {
using(var sv = new Saver(cn)) {
sv.Save();
}
using(var upd = new Updater(cn)) {
upd.Update(); // ошибка
}
}
И опять трассировка стека приведет нас в Update. А если здесь ещё использовать контейнер DI для внедрения IDbConnection, то найти связь между методами сохранения и обновления может быть почти невозможно.

Помимо вводящих в заблуждение исключений, действительно делает эту ошибку замечательной то, что она возникает, когда мы прилагаем дополнительные усилия, пытаясь поступить правильно. Моей внутренней реакцией на это будет раздражение и пассивно-агрессивное отношение к программе:
«Мне очень жаль, что я пытался очистить неуправляемые ресурсы, и это привело к ошибке. Я больше никогда так не буду делать.»

Итого
На первый взгляд IDisposable выглядит просто, но, как и большинство других вещей в жизни, дьявол в деталях. Мы можем защитить себя и свои программы:
- почаще читая документацию,
- подключая анализаторы кода для отслеживания вещей, которые компилятор не может уловить,
- следуя политике очистки, в которой тот, кто вызвал new, должен вызвать и Dispose.

Источник: https://www.lazy-electron.com/2021/03/06/favorite-idisposable-bugs.html
Автор оригинала - Ryan Davis
  • 👍 1
More from @netdeveloperdiary
  1. Oct 11, 2026День 2811. #ВопросыНаСобеседовании Марк Прайс предложил свой набор из 60 вопросов (как тех…
  2. Oct 10, 2026День 2810. #ЧтоНовенького #VSCode Более Быстрый и Лёгкий C# Dev Kit Мы, разработчики, люби…
  3. Oct 9, 2026День 2809. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Окончание Начало 3.…
  4. Oct 8, 2026День 2808. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Начало В ИТ есть се…
  5. Oct 7, 2026День 2807. #ЗаметкиНаПолях Типы Коллекций в .NET, Которые Стоит Попробовать. Окончание Нач…
  6. Oct 6, 2026🦈 Открытое собеседование на Middle C# | 6 октября, 19:00 МСК Приглашаем на открытое собес…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →