tags:

views:

182

answers:

4

Does this make sense ?

Having a simple class

   class Test
   {
     public Test()
     {
        // Do whatever
     }
   }

and then instantiating it

using(new Test())
{
  // Nothing in here
}

The using statement is there just to make sure Test is disposed. When will it be disposed if I just call

new Test()
+11  A: 

Test isn't IDisposable, so that won't even compile. But if it was disposable, yes using will do it, and new by itself won't. It is an unusual usage, but I've seen similar. Rarely.

Based on your comment (main question), I suspect that you are confusing garbage collection and disposal. There is no way to forcibly make something get collected, short of GC (which you should not do). Unless you have a really good reason to want it collected, just let it be - chances are it is "generation 0" and will be collected cheaply anyway.

Also, the "do whatever" suggests doing something in a constructor but not caring about the created object; a static method would be preferable:

public class Test { /* could be static */
     public static void DoSomething() { ... }
}
...
Test.DoSomething();
Marc Gravell
I'd argue on the 'unusual usage', in fact, I use it quite often.
Yossarian
@Yossarian - can you please explain why, and how is it better than a normal method?
Kobi
well : some (initial) action is binded with another (final) action, for example: `HtmlWriter.RenderBeginTag()`, `RenderEndTag()`. If you throw exception between these two (or otherwise forget to `RenderEndTag`), it results in malformed html/xml. So, I wrote extension method over RenderBeginTag, which returns IDisposable class simply calling RenderEndTag, and I now clearly see, (via indentation) where is tag opened/closed. Another examples is measuring of how long did some block take to run. But, YMMV.
Yossarian
@Yossarian - this technique is called RAII (Resource Acquisition Is Initialization). @Kobi - RAII is a cornerstone of reliable software; it is not heavily used currently in .NET (for a variety of reasons), but is entering mainstream (witness, e.g., the Rx library).
Stephen Cleary
Interesting concept. Thanks for giving it a name.
Kobi
@Yossarian - note the "Nothing in here"; it is *that* that makes it unusual
Marc Gravell
@Marc - Sorry, I take back my 'I'd argue' comment, I missed the 'Nothing in here' part.
Yossarian
+2  A: 

By not assigning the instance to a variable, it will be eligible for GC as soon as it goes out of scope.

Or, is there something else you are trying to accomplish with this?

Jordan S. Jones
Nothing else. As Marc underlined I was running my actions in the class constructor which seems to be bad (or at least unusual) practice. I don't need the class further then that.
DrDro
A: 

Recommended reading:

http://msdn.microsoft.com/en-us/magazine/bb985010.aspx

Turek
A: 

I suspect your Test class is of IDisposable type and that you've neglected to show it in your sample?

If you do not call Dispose in your finalizer, Dispose() will never get called (but the object would still be freed).

Try this instead:

public class Test : IDisposable
{
    public void Dispose()
    {
        Console.WriteLn("Dispose");
    }

    ~Test()
    {
        Dispose();
    }
}

Using the above example, if you don't explicitly call Dispose, the finalizer (d'tor) would still be called when the object is garbage collected (freed), hence calling Dispose().

Note the distinction between Finalizer (d'tor) and Dispose(). The gc doesn't know about IDisposable, hence it's up to you to call Dispose() in your finalizer. Also, to help the gc determine if there's a need to Finalize the object prior to 'freeing' it, you'd want to call GC.SuppressFinalize(this) in your Dispose method. For example, if you're calling Dispose() explicitly or implicitly by using "using", then the gc can skip finalizing the object again which only repeats a call to Dispose().

Zach Saw
-1 Calling `Dispose` from a `Finalizer` without an explicit signal that no managed resources can be used (e.g., `Dispose(false)`) is a great way to introduce lurking bugs.
Stephen Cleary
That example was meant to show the OP that Dispose is not called just because you implement IDisposable. It would take a much longer article to explain why you can't reference managed resource when Dispose() is called by the finalizer, hence the need to have Dispose(bool disposing). And, saying what you just did is absolutely not helpful in getting the OP understand the reason behind it.
Zach Saw
BTW, a properly implemented garbage collector would not require a two-path disposer - only one implemented by .NET would. MS only did it for performance reasons, trading off code safety.
Zach Saw