我可以清除使用块内的外部变量吗?

时间:2013-05-07 22:56:43

标签: c# idisposable

我有一个静态StreamWriter字段用于我需要通过lambda函数访问的日志文件,该函数在长时间运行的进程上侦听StandardOutput。

我正在使用字段的null / not-null状态来确定进程是否在另一个线程上忙;需要按顺序执行操作。

我的问题是,当我在使用块中将变量设置为 null 时会发生什么?它还能妥善处理吗?

public class Service
{
    private static StreamWriter logger;

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

            logger = null;
        }
    }
}

3 个答案:

答案 0 :(得分:3)

根据C#参考,§8.13,您的代码:

private static StreamWriter logger;

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

相当于

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();
   }
}

相关引用:

  

表格的使用声明

    using (expression) statement
  

具有相同的三种可能的扩展,但在这种情况下,ResourceType隐式地是表达式的编译时类型,并且资源变量在嵌入语句中是不可访问的,并且是不可访问的。

答案 1 :(得分:2)

  

我的问题是,当我在使用块中将变量设置为 null 时会发生什么?它还能妥善处理吗?

这取决于您的变量声明的位置。它将被正确处理,或者您的代码不会首先编译。

如果您的变量在using语句之外声明:是

A a;
using (a = new A())
{
    a = null;
}

是的,它会妥善处理。对于一个简单的测试:

A variable is nulled within a using block and disposed of successfully
我的文字配色方案为Ragnarok Grey

即使清除了作业,也似乎保留了对new A()的引用。 a语句按预期在using语句的末尾处理,即使它已在内部被删除。

在某些版本的Visual Studio中,这可能会导致Compiler Warning (level 2) CS0728

  

可能错误地赋值给本地'a',这是using语句或lock语句的参数。处理呼叫或解锁将发生在本地的原始值上。

如果在using语句中声明了变量:N / A

using (var a = new A())
{
    a = null;
}

以上代码无法编译。您不允许首先分配到using变量。上面的代码产生了这个编译错误:

  

无法分配给'a',因为它是'使用变量'

这是Compiler Error CS1656

  

当在只读上下文中发生对变量的赋值时,会发生此错误。只读上下文包括 foreach 迭代变量,使用变量和固定变量。要解决此错误,请避免在使用块, foreach 语句和已修复语句中对语句变量进行分配。

答案 2 :(得分:2)

这不是问题。您必须使用ildasm.exe查看IL以查看编译器如何执行此操作。但它会生成一个额外的变量来存储对象的引用,因此你不能像这样射击你的脚。等效的C#代码(粗略地)看起来像这样:

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

额外的$ temp变量可以帮助您摆脱困境。