Когда необходимо утилизировать? - PullRequest
13 голосов
/ 31 июля 2009

Когда у вас есть код вроде:

Bitmap bmp = new Bitmap ( 100, 100 );
Graphics g = Graphics.FromImage ( bmp );

Pen p = new Pen ( Color.FromArgb ( 128, Color.Blue ), 1 );
Brush b = new SolidBrush ( Color.FromArgb ( 128, Color.Blue ) );

g.FillEllipse ( b, 0, 0, 99, 99 );    
g.FillRegion ( b, pictureBox1.Region );

pictureBox1.BackColor = Color.Transparent;
pictureBox1.Image = bmp;

Вы должны утилизировать ручку и кисть? А как насчет BMP и G?

Мой главный вопрос: если их нужно было утилизировать вручную, почему бы их не утилизировать, как только они выйдут из области видимости? Это то, что произойдет, если вы не утилизируете их вручную? Это задержка заставляет людей делать это вручную?

Ответы [ 6 ]

17 голосов
/ 31 июля 2009

Да, вы должны избавиться от них - не только ручкой и кистью, но также Bitmap и Graphics.

Они не удаляются, когда находятся вне области видимости, потому что сами переменные являются ссылками, а не объектами, и компилятор C # не знает, принадлежит ли владелец этим ссылкам или нет (например, FillEllipse может, теоретически, запомните приведенную ссылку и попробуйте использовать ее в более поздний момент - помните, что компилятор языка не обладает специальными знаниями по семантике библиотеки!).

Если вы хотите указать, что право собственности ограничено этой областью, вы используете оператор using:

using (Bitmap bmp = new Bitmap ( 100, 100 ))
using (Graphics g = Graphics.FromImage ( bmp ))
using (Pen p = new Pen ( Color.FromArgb ( 128, Color.Blue ), 1 ))
using (Brush b = new SolidBrush ( Color.FromArgb ( 128, Color.Blue ) ))
{
    g.FillEllipse ( b, 0, 0, 99, 99 );    
    g.FillRegion ( b, pictureBox1.Region );
}

Это заставит компилятор вставлять вызовы к Dispose автоматически по мере необходимости, гарантируя, что все объекты удаляются после того, как соответствующая область действия using оставлена ​​(как правило, путем передачи управления, такой как return или break, или исключение).

Если вы пришли из фона C ++, using в C # прямо аналогичен const std::auto_ptr, за исключением того, что здесь используется языковая конструкция, и его можно использовать только для локальных переменных (т.е. не для полей класса).

6 голосов
/ 31 июля 2009

Я знаю, что другие люди поместили здесь примеры кода, но я начал, поэтому я закончу:

using (Bitmap bmp = new Bitmap(100, 100))
{
  using (Graphics g = Graphics.FromImage(bmp))
  {
    using (Pen p = new Pen(Color.FromArgb(128, Color.Blue), 1))
    {
      using (Brush b = new SolidBrush(Color.FromArgb(128, Color.Blue)))
      {
        g.FillEllipse(b, 0, 0, 99, 99);
        g.FillRegion(b, pictureBox1.Region);

        pictureBox1.BackColor = Color.Transparent;
        pictureBox1.Image = bmp;
      }
    }
  }
}

Я всегда использую using в своем коде, поскольку он автоматически вызывает Dispose() для вашего объекта, даже если в блоке using возникло исключение. Я часто использую его для SharePoint проектов (но это другая история ...).

3 голосов
/ 12 августа 2011

Если одноразовый шаблон используется правильно, Dispose - это , который не является строго необходимым - он будет вызван, когда объект будет завершен, поэтому вы не потеряете ресурсы или что-либо еще.

Тем не менее, это хороший способ позвонить по номеру Dispose, как только вы закончили использовать объект, так как расходные материалы часто напрямую контролируют собственные ресурсы, которые обычно ограничены. Объекты обычно не сразу завершаются / собираются, поэтому эти ресурсы просто теряются, теряются, когда вы больше не используете объект. Утилизация немедленно освобождает эти ресурсы, поэтому они могут использоваться другими частями программы (или, в некоторых случаях, другими программами).

Обратите внимание, что блок using автоматически удаляет объект, когда вы закончите с ним, поэтому вы редко, если вообще видите, Dispose в блоке using.

Краткая версия: если объект реализует IDisposable, и ваш код его создал (т. Е. Если это не системный объект, такой как Pens.Blue или Graphics, передаваемый в OnPaint и т. Д.), Он должен утилизировать, когда вы полностью с этим покончили - либо вызывая Dispose, либо вызывая какой-либо другой метод, который указан для вызова Dispose (Close является распространенным), либо используя блок using , У вас нет , чтобы его утилизировать, но вы почти всегда должны.

3 голосов
/ 31 июля 2009

C # не "разрушает" и не избавляется от вещей, как только они выходят из области видимости.

Эти классы , наиболее вероятно, автоматически освобождают неуправляемые ресурсы, которые они держат в своем специальном методе Finalizer, который будет вызываться, когда они будут собираться мусором в неопределенное время после выхода из области видимости. .

Но полагаться на это - значит полагаться на то, что находится вне вашего контроля и может не произойти какое-то время.

Если класс реализует IDisposable, лучше всего вручную вызвать где-нибудь Dispose() или, предпочтительно, обернуть его в блок using. Таким образом, вы можете быть уверены, что:

A. Неуправляемые ресурсы определенно освобождается.

B. Неуправляемые ресурсы освобождаются как можно скорее.

1 голос
/ 31 июля 2009

Утилизация используется для удаления неуправляемых ресурсов.

Итак, как правило, я включаю любые экземпляры IDisposable объектов в оператор using, поэтому мне не нужно беспокоиться о том, какой неуправляемый ресурс имеет Pen.

1 голос
/ 31 июля 2009

Да, bmp, g, b и p все IDisposable, вы должны удалить () все из них. Желательно с использованием using() {} блоков.

Существуют исключения, когда вы используете Pen p2 = Pens.Blue;, вы не должны избавляться от p2. Это называется стоковым товаром. То же самое для кистей. Черный и т. Д.

Что касается , почему , то же самое для всех одноразовых классов. .Net не использует подсчет ссылок, поэтому нет немедленного действия, когда ссылка выходит из области видимости.

И передача его сборщику мусора в конечном итоге освободит их, но это (очень) неэффективно. Мне известно о приложении ASP.NET (!), Которое не удалось из-за нехватки графических дескрипторов из-за того, что они не были быстро утилизированы. Он генерировал изображения.

...