4

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

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

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

public class Service
{
    private static StreamWriter logger;

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

            logger = null;
        }
    }
}
4

3 回答 3

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 隐含地是表达式的编译时类型,并且资源变量在嵌入语句中是不可访问的,也不可见。

于 2013-05-07T23:42:47.533 回答
2

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

这取决于您的变量的声明位置。它要么被正确处理,要么你的代码一开始就无法编译。

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

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

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

变量在 using 块中为空并成功处理
我的文字配色方案是Ragnarok Gray

即使任务被清除,对 的引用new A()似乎也得到了维护。a按预期在语句末尾处理using,即使它在内部为空。

在某些版本的 Visual Studio 中,这可能会导致编译器警告(级别 2)CS0728

可能不正确地分配给本地“a”,这是 using 或 lock 语句的参数。Dispose 调用或解锁将发生在本地的原始值上。

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

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

上面的代码不会编译。首先,您不允许分配给using变量。上面的代码产生了这个编译错误:

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

这是编译器错误 CS1656

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

于 2013-05-07T23:29:52.843 回答
2

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

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

这个额外的 $temp 变量可以让你远离麻烦。

于 2013-05-07T23:48:01.930 回答