Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Need clarification for using {} statement in C#

Status
Not open for further replies.

IlyaRabyy

Programmer
Nov 9, 2010
568
US
Colleagues,

the C# Reference on the statement in the subject line states: "Provides a convenient syntax that ensures the correct use of IDisposable objects."
The rest is even less comprehensible for yours truly.
The only thing I could derive from that article


was that, whatever memvars were declared within this using {} block, will be properly and safely disposed of (something like free after malloc in C).

Did I get it correctly?

If so - Is it the only useful thing about using {} block?

If not - what else is there that might be useful?

AHWBGA!


Regards,

Ilya
 
Yes, the variable declared in the using statement will automatically be disposed when the using clause ends. I use it a lot when I'm working with the SAP BusinessObjects .NET SDK, part of which is still built on COM objects. I write wrapper classes that include a disposer so that I can make sure that the memory used by the COM object is immediately freed instead of waiting for garbage collection, which can take a while for COM objects.

-Dell

Senior Manager, Data & Analytics
Protiviti
 
Got it, thank you!

Any other reasons to implement this technique?

Regards,

Ilya
 
Like C {} they also go out of scope which is really useful when you write experimental code and cut and paste various bits.
 
OK, got it, thank you, xwb!
Still the following is not exactly clear for this old "newbie" ( [smile] ): "variable(s) disposed off" - is the memory (heap, stack, or both) occupied by declared within the using {} block memvars cleaned out upon exiting out of this block? E.g. if I declared a memvar as a pointer on an object of some class, will it clean out from memory not only the pointer but the object as well?
Or I'd rather run GC.Collect() method within this using{} block myself as the last command in it? (BTW: GC.Collect() w/o arguments - does it clean-up all memvars including public ones? Or just those within the scope of the code block it is issued in?


Regards,

Ilya
 
There is no need to run GC.Collect() explicitly unless you are working on an embedded application where GC is critical. If you take a reference to a local object inside the using, it will not get cleaned up until the reference is released. Taking a reference to a local object can often cause huge memory leaks so it is not recommended.

The clean up does all variables created within the scope of the using that are no longer in use.
 
Not quite sure I follow...
Let me try another approach. Say, you have this class (honestly stolen from MSDN)
Code:
public class CustomClass
   {
      public int Number { get; set; }
      
      public int Multiply(int num)
      {  return num * Number; }
      public CustomClass()
      {  Number = 0;}
   }
public void main()
using {
   CustomClass objTest = new CustomClass(10);
   int iRes = objTest.Multiply(5);
   MessageBox.Show(iRes.ToString());
   }
In the code above, will the memory occupied by objTest, that is CustomClass' instance, be freed along with the objTest pointer (or "reference', if you will) after the closing bracket of the using {} block?
Or I need to do it explicitly by calling in garbage collector?

TIA!


Regards,

Ilya
 
Got it.
Now (digging even deeper): if it's something like
Code:
using (Stream result = new FileStream(tempFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
   {
      using (XmlWriter writer = XmlWriter.Create(result, new XmlWriterSettings { CloseOutput = false })) //Line 1
      using (XmlReader reader = XmlReader.Create(inputFilePath))                                         //Line 2
      using (XmlReader helperReader = XmlReader.Create(inputFilePath))                                   //Line 3
      {
         using (XmlReader ptreader = XmlReader.Create(inputFilePath))                                    //Line 4
// some more code w/o using, and then
       }
    }
when the pointers and objects declared on the lines I've marked "Line1"..."Line4" will be released?
IOW, what's the "signal" for the system to release these thingies? On the closing parenthesis, or at the end of the function (since they're all local), or ... what?

TIA!

Regards,

Ilya
 
Thus, in the code above, since the memvar "result" is declared inside the "using's" brackets (round ones, a.k.a. "parenthesis"), it is discarded right after its declaration?
[ponder]
Or you meant "braces" ("curly" brackes)?
Please clarify.
TIA!

Regards,

Ilya
 
Ignorant as I am (not!), I happen to know the difference between "parenthesis" and "braces", colleague Dell. ;-)
Seriously now:

In the code above, posted on 29 Jan 20 @ 17:24, there are several "using" statements w/o braces, the contents in parenthesis only (lines 1...3). And my question now is:

At what moment the memvars declared within outermost parentheses in those lines, with no braces, will be discarded from memory?

1. Right at the closing parenthesis?
OR
2. When the code block within braces, of which this brace-less (if that's the word) ends? (That including the starting and ending braces of the function/procedure/method it's in.)


Regards,

Ilya
 
I always use a set of braces after each using statement because there are multiple lines of code that the using applies to. However, after looking at the MS documentation for using, I'm going to recommend changing your code to this so that all of your XmlReaders are initialized in the same using block:

Code:
using (Stream result = new FileStream(tempFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
{     
   using (XmlWriter writer = XmlWriter.Create(result, new XmlWriterSettings { CloseOutput = false })) 
     using (XmlReader reader = XmlReader.Create(inputFilePath),
                      helperReader = XmlReader.Create(inputFilePath),                                   
                      ptreader = XmlReader.Create(inputFilePath))  
     {                                  
        // multiple lines of code
     }
}

The documentation [URL unfurl="true"]https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/statements#the-using-statement[/url] indicates that the using block is just shorthand for the following logic:

Code:
{
    ResourceType resource = expression;
    try {
        statement;
    }
    finally {
        if (resource != null) ((IDisposable)resource).Dispose();
    }
}

There are various types of statements that go in the "finally" block depending on whether resource is nullable or dynamic, but the logic is all similar. This means that if there's just a single line of code that the using applies to, you don't need braces and the variable declared in the using will be disposed when the statement completes. If you have multiple lines of code the using applies to, you must use the braces and the variables are disposed when the braces are closed.

-Dell

Senior Manager, Data & Analytics
Protiviti
 
Unfortunately, colleague Dell, this is not mine (but vendor's) program that I need to document... NO-CAN-DO change anything, it's "verbotten". :-(

Regards,

Ilya
 
Following the documentation that I linked to, the three variables inside the outer braces will be disposed when the inner braces are closed.

-Dell

Senior Manager, Data & Analytics
Protiviti
 
Hi Ilya,

the usage of "using" is similar to that of "if" or "for": if only one statement follows, no need for braces, even if that one statement following is another "using" statement.
Therefore, your code is equivalent to something like this:
Code:
using (XmlWriter writer = XmlWriter.Create(result, new XmlWriterSettings { CloseOutput = false })) //Line 1
{ // implicit brace 1
      using (XmlReader reader = XmlReader.Create(inputFilePath))                                         //Line 2
	  { // implicit brace 2
		  using (XmlReader helperReader = XmlReader.Create(inputFilePath))                                   //Line 3
		  {
			 using (XmlReader ptreader = XmlReader.Create(inputFilePath))                                    //Line 4
			 // one line statement or another implicit brace?
		   } // end of scope helperReader, object disposed
	   } // end implicit brace 2, reader end of scope, disposed
} // end implicit brace 1, xmlWriter end of scope, disposed, end of scope for result

No need to change / rewrite any code. What I put above is the exact same as your code, only differently structured so that you can better see the scope of each object and when it is released.

Hope that helps.

Cheers,
MakeItSo

"Knowledge is power. Information is liberating. Education is the premise of progress, in every society, in every family." (Kofi Annan)
Oppose SOPA, PIPA, ACTA; measures to curb freedom of information under whatever name whatsoever.
 
Thank you, MakeItSo!
That's what I suspected: these "implicit braces" (don't like them even more than implicit memvars' declaration) was what "threw me off the rails" (and "drove me up the wall" - or ceiling, rather).
Case's closed.
My gratitude to everybody who helped me here to understand and resolve this problem! [thanks2] [bow]

Regards,

Ilya
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top