Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I clear an external variable inside a using block?

Tags:

c#

idisposable

I have a static StreamWriter field for a log file I need to access through a lambda function that listens to StandardOutput on a long-running Process.

I'm using the null/not-null status of the field to determine if the Process is busy on another thread; the actions need to be performed sequentially.

My question is, what happens when I set my variable to null inside a using block? Will it still get disposed properly?

public class Service
{
    private static StreamWriter logger;

    void Run(string logFile)
    {
        using (logger = new StreamWriter(logFile))
        {
            /* ... */

            logger = null;
        }
    }
}
like image 609
J Bryan Price Avatar asked Mar 25 '23 01:03

J Bryan Price


2 Answers

According to the C# reference, § 8.13, your code:

private static StreamWriter logger;

using (logger = new StreamWriter(logFile))
{
   /* ... */
   logger = null;
}

is equivalent to

private static StreamWriter logger;


{  // using scope
   logger = new StreamWriter(logFile);
   IDisposable resource = logger;       // hidden var inserted by the compiler 
   try
   {
     /* ... */
     logger = null;
   }
   finally
   {
      if (resource != null)  
        resource.Dispose();
   }
}

The relevant quote:

A using statement of the form

    using (expression) statement

has the same three possible expansions, but in this case ResourceType is implicitly the compile-time type of the expression, and the resource variable is inaccessible in, and invisible to, the embedded statement.

like image 155
Henk Holterman Avatar answered Mar 31 '23 17:03

Henk Holterman


This is not a problem. You'd have to look at the IL with ildasm.exe to see how the compiler does this. But it generates an extra variable to store a reference to the object so you cannot shoot your foot like this. The equivalent C# code would (roughly) look like this:

StreamWriter $temp = new StreamWriter(logFile);
logger = $temp;
try {
   // etc...
   logger = null;
}
finally {
   if ($temp != null) $temp.Dispose();
}

That extra $temp variable keeps you out of trouble.

like image 32
Hans Passant Avatar answered Mar 31 '23 17:03

Hans Passant