V3114. IDisposable object is not disposed before method returns.
Чтобы понять смысл данной диагностики, давайте для начала немного вспомним теорию.
Сборщик мусора автоматически освобождает память, связанную с контролируемым объектом, если он больше не используется и на него не осталось видимых ссылок. Тем не менее, невозможно предсказать, когда именно произойдёт сборка мусора (если не вызывать её вручную). Кроме того, сборщик мусора не имеет информации о таких неуправляемых ресурсах, как дескрипторы, окна или открытые файлы и потоки. Метод 'Dispose' обычно используется, чтобы освобождать такие неуправляемые ресурсы.
Понимая это, анализатор обнаружил локальную переменную, объект которой реализует интерфейс 'IDisposable' и не передается за пределы зоны видимости локальной переменной. При этом после использования данного объекта не был вызван метод 'Dispose' освобождающий принадлежащие ему неуправляемые ресурсы.
Если предположить, что данный объект содержит какой-либо дескриптор (например, файл), то он будет оставаться в памяти до следующей сборки мусора, которая произойдет через неопределенный промежуток времени вплоть до момента завершения работы программы. В результате файл может неопределённое время оставаться заблокированным, мешая нормальной работе других программ или операционной системе.
Рассмотрим пример такой ситуации:
string Foo()
{
var stream = new StreamReader(@"С:\temp.txt");
return stream.ReadToEnd();
}
В данном случае объект 'StreamReader' будет хранить в себе дескриптор открытого файла даже после выхода из метода 'Foo', тем самым блокируя его для других программ и операционной системы до тех пор, пока сборщик мусора не очистит его.
Чтобы избежать этого - своевременно освобождайте ресурсы, используя метод 'Dispose' как в примере ниже:
string Foo()
{
var stream = new StreamReader(@"С:\temp.txt");
var result = stream.ReadToEnd();
stream.Dispose();
return result;
}
Однако, для более надёжного освобождения ресурсов рекомендуется использовать конструкцию 'using'. Она обеспечит автоматическую очистку ресурсов используемого объекта после завершения:
string Foo()
{
using (var stream = new StreamReader(@"С:\temp.txt"))
{
return stream.ReadToEnd();
}
}
Компилятор раскроет блок 'using' в блок 'try finally', и в 'finally' вставит вызов метода 'Dispose' - это гарантирует очистку объекта даже в случае возникновения исключений.
Данная диагностика классифицируется как:
Взгляните на примеры ошибок, обнаруженных с помощью диагностики V3114. |