5

I have a simple Windows form application. On the form I have a custom class that has it's own Dispose method.

So the question is when should I call this?

Is the FormClosed event (i.e. Form1_FormClosed) the correct place to do this? Or should I be writing a custom Dispose method for the form?

For bonus points: Can a from be reopend once closed? (Obviously if it can then the FormClosed is the wrong way to go!)

Thanks.

AidanO
  • 868
  • 1
  • 11
  • 33

4 Answers4

7

A wee bit of surgery is required. Open the node next to your form in the Solution Explorer window. Double-click the Designer.cs file for the form. Locate the Dispose() method and cut-and-paste it into your form's source code file. Now you can alter it and call the Dispose methods on the disposable object references in your form class.

Pre-empting: no, it is okay to edit this part of the designer file. Only the section in the #region is off limits.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
5

Controls that implement IDisposable should be added to the System.ComponentModel.IContainer components property of the form.

In the dispose of the form all disposables in that collection will be disposed of. (All puns intended)

EDIT To see this just drop a Timer on the form and have a look at the generated code.

Emond
  • 50,210
  • 11
  • 84
  • 115
  • That looks like a neat solution. Wouldn't I need to implement the IComponent and associated ISite for any objects I want dispose though? I'm torn on wheither there is any value add to this. – AidanO Jan 26 '11 at 12:10
  • 1
    Yes, but these allow you to 'drop' the control on the design surface so they are a part of developing a component. If you do not want to use the designer to add and configure the component it probably is not a control/component. (I never liked the 'invisible' controls such as Timer) If it is not a control you could implement the same trick with a 'class Disposables : List, IDisposable {}' and dispose of it in the Dispose of the form or any other method you'd like. – Emond Jan 26 '11 at 12:22
  • I really like your answer and I've up rated it as much as I can, however I think Hans's answer more directly answers the question asked. A combinatation of both will be what I'll be using. If I could share credit I would. – AidanO Jan 27 '11 at 09:12
  • Thanks! To be honest I don't like the modifying the generated code. They should have put the Dispose/Disposing method in the user-code-partial class. But it is the only way... – Emond Jan 27 '11 at 11:49
0

If you have reason then on form closing you should verify bool Application.IsExiting.

If you want not to destroy form then on form closing cancel closing and do Hide(). Then form can be reopened using Show(). The whole form state will remain the same.

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
Sasha Reminnyi
  • 3,442
  • 2
  • 23
  • 27
  • Sorry to be thick but why should I check the Application.IsExiting? I knew of the "this.Hide(); e.Cancel = true; " So to my mind if I'm not doing that, then the form is closing and can't be reopened. It can be recreated, but that's fine too. – AidanO Jan 26 '11 at 11:34
  • I thought you need one form instance per app lifetime. In your case you need somehow to notify your closing method that you want only to hide or to close the form. for instance, add some static `bool NeedsClosing` to the form and verify it before closing. – Sasha Reminnyi Jan 26 '11 at 11:46
-1

Never call dispose if you don't have a really good reason for doing so.

If the object contains an heavy object (Image, database connection etc) call a close as soon as you're done with it.

Calling a dispose on a close forces you to reload the resource on an open. A form can be reopened if you don't destroy any important items after closing it and keep a reference.

By 'definition' close does the same thing as 'dispose' (and it closes windows/forms). Every close call in the .net framework just calls dispose internally anayway.

@comment

I've used an application that kept around 40MB bitmaps. Calling dispose on those really helped on the memory bound machine. Calling dispose on objects with the information given in the question is impossible. Calling it 'just because' is bad, calling it because the designer does it is even worse.

CodingBarfield
  • 3,392
  • 2
  • 27
  • 54
  • Let's say I have a really good reason, but I only want to call it when I know it's no longer going to be used. So if the form can be reopened I won't be calling the Dispose. Should I then move my Dispose of the object to the Dispose of the Form? – AidanO Jan 26 '11 at 11:24
  • @Barfieldmv: Dispose methods are there to be called, the only reason you need is that 'you're done with the instance'. Calling a `Close` is only appropriate if A) a `Close` method exists, B) the instance is reusable (by means of an `Open` method or something similar) and C) you know this and do want/need to reuse the instance. – Grant Thomas Jan 26 '11 at 11:37
  • @Mr. Disappointment Don't judge to fast. Yes, we have such interface. But calling it should be wise. In case of framework, CLR will do everything without your intrudance. – Sasha Reminnyi Jan 26 '11 at 11:48
  • @LexRema: The CLR does a lot, but it isn't a palm-reader of sorts, you, as a developer, have responsibilities. http://stackoverflow.com/questions/45036/will-the-gc-call-idisposable-dispose-for-me. – Grant Thomas Jan 26 '11 at 11:51
  • @Mr. Disappointment I didn't say CLR will call Dispose. I meant it will clear resources wisely. And Disposable is needed in your objects if you create some unmanaged objects. to explicitly destroy them. – Sasha Reminnyi Jan 26 '11 at 11:55
  • @LexRema: It is required to explicitly destroy managed objects, too! – Grant Thomas Jan 26 '11 at 12:08
  • @Mr. Disappointment No. Show me such requierment. There is no such in .NET world. – Sasha Reminnyi Jan 26 '11 at 12:12
  • @LexRema: Dude, are you insane? Just look at `FileStream`, for instance, which, if not disposed, could potentially lock a file for an non-deterministic amount of time! (Yes I know `FileStream` will destroy unmanaged objects, but we don't care about that, what WE care about is that `FileStream` must be disposed of in order to release it's resources, managed or not. – Grant Thomas Jan 26 '11 at 12:40
  • Off course, in case of FileStream. In general (CLR via C#, p.551): In general,I strongly discourage calling a Dispose or Close method. The reason is that the CLR’s garbage collector is well written,and you should let it do its job. The garbage collector knows when an object is no longer accessible from application code, and only then will it collect the object. When application code calls Dispose or Close, it is effectively saying that it knows when the application no longer has a need for the object. For many applications,it is impossible to know for sure when an object is no longer required. – Sasha Reminnyi Jan 26 '11 at 13:19
  • I can see this point, however, I disagree inasmuch as `IDisposable` ought only to be implemented on types with unmanaged resources anyway (according to MSDN) which you are responsible for cleaning by means of calling `Dispose`, and if you don't know a type utilises unmanaged elements then you're neglecting this responsibility if not disposing, and even if you do know the type _doesn't_ use unmanaged resources then see 'future-proofing', as we should assume such a pattern is implemented for a reason. So, in short, if we're talking about the GC cleaning up, it's an irrelevant point in this case. – Grant Thomas Jan 26 '11 at 13:41
  • From MSDN: _Because the Dispose method must be called explicitly, objects that implement IDisposable must also implement a finalizer to handle freeing resources when Dispose is not called. By default, the garbage collector automatically calls an object's finalizer prior to reclaiming its memory. However, once the Dispose method has been called, it is typically unnecessary for the garbage collector to call the disposed object's finalizer. To prevent automatic finalization, Dispose implementations can call the GC.SuppressFinalize method._ – Grant Thomas Jan 26 '11 at 13:45
  • Just to clarify, all I'm getting at is that you should know when to call `Dispose` for any given type you're working with, but you ought not to just forget about it and think it is all handled for you. – Grant Thomas Jan 26 '11 at 13:49
  • Yes, you should understand when that freeing is really needed. For example Bitmap also has that method, but it's not so relative for Bitmap to call dispose as for FileStream. – Sasha Reminnyi Jan 26 '11 at 14:03
  • 1
    Abandoning IDisposable objects is bad unless one knows that present, future, and derived versions of those objects may be abandoned safely. Some objects receive events from long-lived or static objects and rely upon Dispose to detach those events. If one of your objects receives events from such an object, failure to dispose it may prevent your object--or other objects it references--from EVER being garbage-collected. Although on some occasions one may have little choice but to rely upon a finalizer, such cases should be the exception rather than the rule. – supercat Jan 26 '11 at 16:36