13

When you have code like:

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;

Do you have to dispose the pen and brush? What about bmp and the g?

My main question is, if these were to be disposed manually, why don't they get disposed as soon as they get out of the scope? Is that what would happen, if you didn't dispose them manually? Is it the delay that makes people do this manually?

Brad Mace
  • 27,194
  • 17
  • 102
  • 148
Joan Venge
  • 315,713
  • 212
  • 479
  • 689

6 Answers6

17

Yes, you have to dispose them - not just pen and brush, but also Bitmap and Graphics.

They don't get disposed when they're out of scope because the variables themselves are references, not objects, and C# compiler doesn't know whether the ownership still belongs to those references or not (e.g. FillEllipse could, in theory, remember the reference it's given, and try to use it at some later moment - remember that language compiler doesn't have any special knowledge of library semantics!).

If you want to indicate that ownership is restricted to that scope, you use the using statement:

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 );
}

This will make the compiler insert calls to Dispose automatically as needed, ensuring that all objects are disposed once the corresponding using scope is left (whether normally, by control transfer such as return or break, or an exception).

If you come from a C++ background, using in C# is directly analogous to a const std::auto_ptr, except that it's a language construct here, and can only be used for local variables (i.e. not for class fields).

Pavel Minaev
  • 99,783
  • 25
  • 219
  • 289
  • 1
    Really? Interesting. I've never seen that for anything but the Graphics object before. Is there an MS site that talks about this in more detail? – derGral Jul 30 '09 at 21:54
  • 4
    It's true that you should call `Dispose` or employ the `using` statement, but it's not true that the `Pen` will otherwise not be disposed out of scope because some API might be using it. `Pen` has a finalizer, which will run at some unspecified time after it becomes unreachable (for a short-lived object it can be pretty soon after), and when that happens, it does the equivalent of `Dispose`. – Daniel Earwicker Jul 30 '09 at 22:19
  • 1
    See: http://msdn.microsoft.com/en-us/library/system.drawing.pen.dispose.aspx - "call Dispose... Otherwise, the resources it is using will not be freed until the garbage collector calls the Pen object's Finalize method." – Daniel Earwicker Jul 30 '09 at 22:20
  • Earwicker, these objects are gonna be added to the Finalization queue only after GC has started, right? – Joan Venge Jul 30 '09 at 22:28
  • 3
    Ryan, if it implements `IDisposable`, then someone somewhere should dispose it. In this case, it's pretty obvious that no code but ours can do this. Earwicker is correct that there is also a finalization mechanism to clean up if you forget to dispose, but as it is undetermined where it kicks it (it may even happen as late as your application shutdown), you may get severe leaks if you do not dispose explicitly; in general, relying on finalizers for such cases is a very bad idea. – Pavel Minaev Jul 30 '09 at 23:08
  • 1
    @Pavel, I tried Disposing the "bmp" too, but it causes an exception when it's disposed after assigned to the Image property of a control. – Joan Venge Jul 31 '09 at 18:37
  • 3
    Well, naturally, because if you assign it to the `Image` property, then control uses it, and you shouldn't dispose it while it's in use. – Pavel Minaev Jul 31 '09 at 19:31
  • @Joan: those objects will be added to the Finalization Queue when the GC does Mark&Sweep, and the finalizers are run on a separate thread after GC has finished. – H H Aug 04 '09 at 00:11
6

I know other people have put code examples here, but I started so I'll finish:

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;
      }
    }
  }
}

I always use using in my code since it calls Dispose() on your object automatically, even if there is an exception raised in the using block. I use it a lot for SharePoint projects (but that's another story...).

Pooven
  • 1,744
  • 1
  • 25
  • 44
Jason Evans
  • 28,906
  • 14
  • 90
  • 154
  • 3
    Correct, but it is (becoming) customary to fold multiple usings to 1 brace pair, like in Pavels sample. – H H Jul 30 '09 at 21:58
  • 2
    Cool, I haven't seen that technique before. Think I'll start using it (no pun intended) from now on :) – Jason Evans Jul 30 '09 at 22:23
  • Yester I answered a [question](http://stackoverflow.com/q/14946381/799558) related to disposing a bitmap after assigning it to `pictureBox1.Image` and my answer was exactly like yours (I already deleted my answer). they told me the picture image will also get disposed. can I still use `using` in this situation? – Abdusalam Ben Haj Feb 19 '13 at 11:46
  • see my [deleted](http://i.stack.imgur.com/t90at.jpg) answer for more clarification – Abdusalam Ben Haj Feb 19 '13 at 11:51
3

C# doesn't "destruct" or dispose of things as soon they go out of scope.

Those classes will most likely automatically free the unmanaged resources that they hold on to in their special Finalizer method, which will be called when they are garbage collected at an indeterminate time after going out of scope.

But to rely on that is to rely on something that is out of your control, and might not happen for a while.

If the class implements IDisposable, best practice is for you to manually call Dispose() somewhere, or preferably wrap it in a using block. That way you can be sure that:

A. The unmanaged resources are definitely being freed.

B. The unmanaged resources are freed as soon as possible.

xyz
  • 27,223
  • 29
  • 105
  • 125
3

If the disposable pattern is used correctly, Dispose is not strictly necessary -- it will be called when the object is finalized, so you won't leak resources or anything.

However, it's good manners to call Dispose as soon as you're done using the object, as disposables often directly control native resources which are usually limited. Objects don't normally get finalized/collected right away, so those resources are just hanging around, wasted, once you're not using the object anymore. Disposing frees those resources immediately, so they can be used by other parts of the program (or in some cases, by other programs).

Note, a using block automatically disposes the object when you're done with it, which is why you rarely if ever see Dispose within a using block.

Short version: If the object implements IDisposable, and your code created it (ie: if it's not a system object like Pens.Blue, or the Graphics you get passed in OnPaint etc), it should be disposed when you're totally done with it -- whether by calling Dispose, or by calling some other method that's specified to call Dispose (Close is a common one), or by using a using block. You don't have to dispose it, but you almost always should.

cHao
  • 84,970
  • 20
  • 145
  • 172
  • 1
    A lot of objects won't clean themselves up if abandoned. While cleanup is fairly simple in some cases, in others it's essentially impossible. Unless one happens to know that it's safe to abandon objects of a particular class, one should assume that abandoning objects without calling Dispose first will cause bad things to happen. – supercat Aug 31 '11 at 00:12
  • Any object that implements IDisposable properly *will* clean itself up if abandoned. As do all disposables in the BCL. Any object that doesn't should have its creator found and fired, as it's not at all difficult to do -- in almost all cases, you can just call `Dispose` in the finalizer -- and anyone messing around with native resources should be intimately aware of what happens when they're not released properly. Anyone not directly messing around with native resources doesn't really need to implement IDisposable. – cHao Aug 31 '11 at 09:01
  • Suppose one wants to construct a class ChangeCounter whose constructor accepts an INotifyPropertyChanged object, and which will report how many times that object has raised its PropertyChanged event since it (the ChangeCounter) was created. By what means could such a class clean up after itself if abandoned? Bear in mind that INotifyPropertyChanged does not promise that implementations of PropertyChanged.RemoveHandler can be used safely from the finalizer thread. – supercat Aug 31 '11 at 15:49
  • Do you know of *ANY* way of implementing a ChangeCounter object that would behaves as described, and clean up after itself, without relying upon the passed-in INotifyPropertyChanged objects to behave in ways not required by the interface? Given that the most popular way of implementing RemoveHandler methods isn't really thread-safe (it will block if another thread holds a lock on the object from which one is trying to remove events), calling PropertyChanged.RemoveHandler would seem very dangerous. – supercat Aug 31 '11 at 16:54
  • I can see many ways by which an interface similar to INotifyPropertyChanged could be defined that would allow for safe cleanup in case subscribers are abandoned, but I see no way for a class that subscribes to an event from an INotifyProperty to clean up after an abandoned instance of that subscriber class, nor do I see any means by which an implementation of INotifyProperty could automatically clean up after an abandoned subscriber. Can you suggest any method, no matter how clunky, by which this could be accomplished without being dependent on behaviors not specified in the interface? – supercat Aug 31 '11 at 17:03
  • If you indeed can't clean up in the finalizer, then your ChangeCounter probably should not implement IDisposable. *Correctly implemented disposables must implement a finalizer that cleans up after them* (read: calls `Dispose`) in case `Dispose` is not called. If your use case is such that you can't clean up in the finalizer, then you can't implement the disposable pattern correctly, and thus probably shouldn't be implementing it at all. – cHao Aug 31 '11 at 20:22
  • I won't harp on the incorrectness of using `IDisposable` for this purpose, as i'm aware it's just an example...but unless the ChangeCounter has its own native resources, it shouldn't be implementing IDisposable anyway. This isn't the fault of the interface; it's the fault of the class not doing what it promised it would when it implemented the interface. – cHao Aug 31 '11 at 20:23
  • As for how you'd implement such a class, well...you might consider a wrapper around the actual subscriber. The subscriber would have a weak reference to the wrapper. You handle references of the wrapper, and when you're done with it, let it fall out of scope and become GC'able. When the subscriber receives an event notification, and sees that the wrapper has been GC'ed, it could remove itself from the notification list, which would presumably remove the only remaining reference and make the subscriber itself GC'able. – cHao Aug 31 '11 at 20:41
  • Wrapping a reference to the subscriber in a WeakReference doesn't quite work, since there will be no way for the WeakReference itself to be eligible for collection until either the event publisher goes out of scope or the collection gets modified, and there's no guarantee either of those will occur before an arbitrary number of subscribers have been created and abandoned. Using IDisposable to clean up subscriptions will work better than any other cleanup method if users of the class call Dispose. It's only when users of the class fail to do so that problems occur. – supercat Aug 31 '11 at 21:03
  • What i'm saying is, the *subscriber* holds the WeakReference to the *wrapper*. When the wrapper gets GC'ed (which *will* happen, because only your code refers to the wrapper -- the INotifyPropertyChanged only has a reference to the *subscriber*), the WeakReference becomes "not alive" and the subscriber can see this and remove its handler from the invocation list. – cHao Aug 31 '11 at 21:09
  • It's possible, albeit tricky, to construct an event subscriber in such a way that Finalize() will get called when all uses other than the subscription itself have gone out of scope. The problem is that unless the event publisher guarantees that it's safe to call RemoveHandler from within the finalizer thread (INotifyPropertyChanged makes no such guarantee), there's no standard way for the Finalize() method to tell the object implementing INotifyPropertyChanged to remove the subscription. Many solutions almost work, but all working solutions require publishers and subscribers to cooperate. – supercat Aug 31 '11 at 21:16
  • Thing is, though, you don't *have* to remove the handler in the subscriber's finalizer. If you want, you can just have an `IsAlive` flag in the subscriber, that the wrapper's finalizer sets to `false`. Then let the subscriber remove itself with every notification from then on, til it orphans itself. And if you're intent on implementing `IDisposable`, you can do so without issues. (When you `Dispose`, just tell the subscriber to remove all the handlers then and there. Otherwise, set `subscriber.IsAlive = false` in the wrapper's finalizer, and let the subscriber clean itself up.) – cHao Aug 31 '11 at 21:36
1

Yes, bmp, g, b and p are all IDisposable, you should Dispose() all of them. Preferably by using using() {} blocks.

There are exceptions, when you use Pen p2 = Pens.Blue; yous should not dispose p2. It's called a stock item. The same for Brushes.Black etc.

As for the why, it's the same for all disposable classes. .Net does not use reference counting so there is no (cannot be) an immediate action when a reference goes out of scope.

And leaving it to the Garbage collector will eventually free them but it is (very) inefficient. I know of an ASP.NET (!) application that failed on a shortage of Graphic handles because of not promptly disposing them. It was generating images.

H H
  • 263,252
  • 30
  • 330
  • 514
  • Thanks Henk. What happens if you call Dispose on Pens.Blue? Is it bad? – Joan Venge Jul 30 '09 at 22:17
  • 1
    You know, i don't really know. I'll take a guess before i try: either you get an exception immediately or nothing happens. – H H Jul 30 '09 at 22:21
  • 1
    I tried: you get an System.ArgumentException with the message that changes aren't allowed. – H H Jul 30 '09 at 22:25
1

Dispose is used to dispose of unmanaged resources.

So, as a rule of thumb, I wrap any instantiations of IDisposable objects in a using statement, so I don't have to worry about what unmanaged resource a Pen has.

Aaron Daniels
  • 9,563
  • 6
  • 45
  • 58