Удаление объекта Graphics
В содержимом последних нескольких страниц можно было заметить, что в некоторых из приведенных примеров непосредственно вызывался метод Dispose() объекта Graphics, в то время как в других это не делалось. Учитывая, что тип Graphics манипулирует различными неуправляемыми ресурсами, имело бы смысл, чтобы он освобождал ресурсы через вызов Dispose() как можно скорее (вместо того, чтобы дожидаться, пока это сделает сборщик мусора в процессе финализации). То же самое можно сказать о любом типе, поддерживающем интерфейс IDisposable. При работе с объектами GDI+ Graphics следует помнить о следующих правилах:
- если вы напрямую создали объект Graphics, вызывайте Dispose(), когда надобность в нем отпадет;
- если вы ссылаетесь на существующий объект Graphics, не вызывайте Dispose().
Чтобы прояснить мысль, рассмотрим следующий обработчик события Paint:
private void MainForm_Paint(object sender, PaintEventArgs e)
{
// Загрузить локальный файл *.jpg.
Image myImageFile = Image.FromFile("landscape.jpg");
// Создать объект Graphics на основе изображения.
Graphics imgGraphics = Graphics.FromImage(myImageFile);
// Визуализировать новые данные в изображение.
imgGraphics.FillEllipse(Brushes.DarkOrange, 50, 50, 150, 150);
// Нарисовать изображение в Form.
Graphics g = e.Graphics;
g.DrawImage(myImageFile, new PointF(0.0F, 0.0F));
// Освободить созданный нами объект Graphics.
imgGraphics.Dispose();
}
Пусть пока вас не волнует, что некоторая логика GDI+ выглядит несколько загадочно. Однако следует заметить, что вы получили объект Graphics из файла *.jpg, загруженного из локального каталога (статическим методом Graphics.FromImage()). Поскольку вы явно создали этот объект Graphics, практический опыт требует вызова метода Dispose() на этом объекте по завершении его использования, чтобы освободить внутренние ресурсы для использования другими частями системы.
Обратите внимание, что вы не вызываете Dispose() на объекте Graphics, который получили из входящего PaintEventArgs. Это объясняется тем фактом, что вы не создавали этот объект напрямую, и не можете быть уверены, что он не понадобится другим частям программы. Ясно, что освобождение объекта, используемого потом где-то еще, создало бы проблему!
Кстати, если вы забудете вызвать Dispose() на объекте, реализующем IDisposable, внутренние ресурсы будут в конечном итоге освобождены, когда позднее до них доберется сборщик мусора. В этом свете ручное освобождение объекта imgGraphics технически не обязательно. Хотя явное освобождение объектов GDI+, созданных напрямую — разумная мера, для простоты в примерах кода это делаться с каждым типом GDI+ не будет.