0

Let's say, I have the following code:

theIDisposableObject myMethod()
{
   theIDisposableObject smth=new theIDisposableObject();
   return smth;
}

void Main()
{
    var A= myMethod();
    ...
    A.Dispose();
}

Do I do it correctly? i mean, is smth disposed on itself, because it is referred to by A variable (which is being disposed), or even smth needs its own disposal (if so, only with using is the solution)?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
T.Todua
  • 53,146
  • 19
  • 236
  • 237

2 Answers2

4

Is the object disposed? Yes.

Is there a better way? Yes. Use the using statement.

AnIDisposableObject myMethod()
{
   AnIDisposableObject smth=new AnIDisposableObject();
   return smth;
}

(...)

using( var a = myMethod()) 
{

}
// a is disposed here.

This is important because if an exception is thrown between var A= myMethod(); and A.Dispose(); A would not be disposed. Bad.


C#8

In C#8 things get even easier.

if (...) 
{ 
   using FileStream f = new FileStream(@"C:\users\jaredpar\using.md");
   // statements
}

// Equivalent to 
if (...) 
{ 
   using (FileStream f = new FileStream(@"C:\users\jaredpar\using.md")) 
   {
    // statements
   }
}

The lifetime of a using local will extend to the end of the scope in which it is declared. The using locals will then be disposed in the reverse order in which they are declared.

{ 
    using var f1 = new FileStream("...");
    using var f2 = new FileStream("..."), f3 = new FileStream("...");
    ...
    // Dispose f3
    // Dispose f2 
    // Dispose f1
}
tymtam
  • 31,798
  • 8
  • 86
  • 126
  • Updated the answer with info about scope. – tymtam Nov 09 '19 at 14:12
  • Nice new pattern there. It's writing first confused my eyes: `using FileStream f = new FileStream(@"C:\users\jaredpar\using.md");` If I see a Semikolon after something that should use brackets, I asume it is a faulty order. Of course this is the using variable modifier, not the using block. Because we had not enough different uses for using :) – Christopher Nov 09 '19 at 15:17
1

Is it Disposesd? In most cases yes.

The code you showed us makes no sense. There has to be something else between the function call and the Dispose call to even consider writing it like this. And those can all throw exceptions, casually skipping over dispose.

I have one rule for IDisposeables:

Never split up the creation and disposing of a IDisposeable across multiple pieces of code. Create. Use. Dispose. All in the same piece of code, ideally using a Using Block. Everything else is just inviting problems.

The rare exception is when you wrap around something Disposeable. In that case you implement iDisposeable for the sole purpose of relaying the Dispose call to the contained instance. That is btw. the reason for about 95% of all IDispose Implementations - you may wrap around something that may need a Dispose.

using is just a shorthand for a: try, finally, NullCheck, Dispose. And finally runs in every possible case: it runs after a return. It runs on exception. It runs on GOTO's, continues and other jumps out it's block. It does not run on the OS killing the processe, but at that point it is kinda the OS/Finalizers responsibility anyway.

The best way of course would be not to return something disposeable from a function. Whatever data it has, just map it to something that does not use Disposeables. IIRC when working with SQLDataReader (wich requires a open connection), that is exactly what happens. You map the Query return value to any other collection that does not need a open connection.

If you can not do that, I would modify your code like this for peace of mind:

void Main()
{
    using(var A= myMethod()){
      //Anything you want to do with that variable
    }
    //using takes care of the Dispose call
}

Now anything can happen and I know using takes care of Disposing.

Christopher
  • 9,634
  • 2
  • 17
  • 31
  • I thought it was clear that the object was used before disposing, but i've modified question. thanks ! – T.Todua Nov 09 '19 at 13:34
  • @T.Todua: My answer stays the same. Just put whatever the eplises stand for inside the using block. As I just verified, not even ThreadAbortedException can break out of a finally. Other exceptions of course still can, but using has the null check it needs to avoid the 1 relevant exception. – Christopher Nov 09 '19 at 15:07