2

I have some code just like below. I am using my sql connection class in a using block. When it finishes the job, it disposes the connection as it is supposed to do. I also have some kernel classes in the same using block and i want them to get disposed when the using block that they are in finishes the job.

I searched a little bit but couldn't find an answer. Does the using block dispose all objects that are inside it's blocks or does it just dispose the object that wrote as parameter? I hope i asked properly. I just want to understand and i don't want to keep writing unnecessary using blocks.

using (SqlConnection conn = new SqlConnection("server=" + serverName + ";initial catalog=" +
                                                      dataBase + ";integrated security=false;uid=" +
                                                      sqlUser + ";password=" + sqlPass + ";"))
{
    Kernel kernel = new Kernel();
    Sirket sirket = default(Sirket);
    Fatura fatura = default(Fatura);
    try
    {
        sirket = kernel.yeniSirket(TVTTipi.vtMSSQL,
                                      "vt adı",
                                      "vt kull adı",
                                      "vt kull sifre",
                                      "netsis kull adı",
                                      "netsis kull sifre",
                                      sube kodu);
        fatura = kernel.yeniFatura(sirket, TFaturaTip.ftSFat);
        fatura.OkuUst("A00000000000011", "C0001");
        fatura.OkuKalem();
        fatura.kayitSil();
    }
    finally
    {
        Marshal.ReleaseComObject(fatura);// those are releasing the objects. if i didn't use those methods would they get disposed immediately as using block finishes.
        Marshal.ReleaseComObject(sirket);
        kernel.FreeNetsisLibrary();
        Marshal.ReleaseComObject(kernel);
    }

}
JohnChris
  • 1,360
  • 15
  • 29
S. Ozbek
  • 41
  • 7
  • 2
    multiple using blocks needed, using will only dispose the `IDisposable` that u put in the brackets: e.g. using(xxxx) - only xxx gets disposed, nothing else inside will, to further clarify, my answer is with regards to `IDisposables` that need to get closed, normal GC will work on objects within the using. So for example if within your sql connecting u opened a `Stream` u would have to put that in a `using` as well – JohnChris Jun 07 '19 at 11:36
  • 3
    Also, new with C# 8 is the using declaration. It allows you to declare a variable as using like so `using var conn = new SqlConnection(...);` without having a using block. It will then automatically dispose of every variable declared like this once the variable goes out of scope – MindSwipe Jun 07 '19 at 11:38
  • 1
    @MindSwipe mmm c#8 ftw, i like that – JohnChris Jun 07 '19 at 11:41
  • 1
    Please note that niether of the instances inside the using statement gets disposed in the code sample in the question. `Dispose` is not the same as `Marshal.ReleaseComObject`... – ATC Jun 07 '19 at 11:44
  • 1
    Is the question: "Can I use `using` statement instead of `Marshal.ReleaseComObject()`" ? The answer is nope, but you can easily make own wrapper class to abuse (in a good way) `IDisposable` and achieve that. – Sinatr Jun 07 '19 at 11:49

4 Answers4

4

No, using will only dispose the one object.

However, nested using blocks can be written like this:

using (var con = new SqlConnection())
using (var kernel = new Kernel())
{
    // ...
} // Disposes kernel and con

Note that COM objects are not released with using. For that, you need the finally block as written. Just put the dispose call there, too.

An alternative would be a wrapper, that also frees the COM object. Outline:

class ComReleaseWrapper : IDisposable
{
    object _obj;
    public ComReleaseWrapper(object o) {
       _obj = o;
    }
    public object Object { get { return _obj; } }

    public void Dispose() {
        if (_obj != null) {
            Marshal.ReleaseComObject(_obj);
            if (_obj is IDisposable d) d.Dispose();
        }
        _obj = null;
    }
 }

 using (var kernelWrap = new ComReleaseWrapper(new Kernel()) {
    var kernel = kernelWrap.Object as Kernel;
 }
king_nak
  • 11,313
  • 33
  • 58
  • Mind that `kernel` is a COM Object. OP is doing `Marshal.ReleaseComObject(kernel);`. As Sinatr writes correctly, it could be wrapped in an IDisposable, though. – Fildor Jun 07 '19 at 12:17
  • 1
    You're right, didn't pay attention to that... In that case, I would actually prefer the finally block with explicit dispose if this is a one time use case. Otherwise, a wrapper class would be a good solution – king_nak Jun 07 '19 at 12:24
1

It disposes only the variable defined as in this case would be SqlConnection. If you have multiple items to dispose you could however stack them as follows to keep the code better readable:

using (var f1 = new FileStream(@"C:\temp\file.txt", FileMode.Open))
using (var f2 = new FileStream(@"C:\temp\file.txt", FileMode.Open))
using (var f3 = new FileStream(@"C:\temp\file.txt", FileMode.Open))
{
    //do stuff with filestreams here
}
NotFound
  • 5,005
  • 2
  • 13
  • 33
1

The using block only disposes the object initialized in the parenthesis.

using (var conn = new SqlConnection(connectionString))
{
    // Do all sort of stuff here with other disposable things
} // At this point in the code, only the SqlConnection gets disposed.

The using block is syntactic sugar for try...finally - so the previous code actually gets translated to this:

var  conn = new SqlConnection(connectionString);
try
{
    // Do all sort of stuff here with other disposable things
}
finally
{
    // At this point in the code, only the SqlConnection gets disposed.
    ((IDisposable)conn).Dispose();
}
ATC
  • 907
  • 1
  • 9
  • 14
0

No it is not necessary to use using inside using.

It is a wrapper so that we don't have to explicitly dispose object.