我有一个静态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;
}
}
}
答案 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 时会发生什么?它还能妥善处理吗?
这取决于您的变量声明的位置。它将被正确处理,或者您的代码不会首先编译。
A a;
using (a = new A())
{
a = null;
}
是的,它会妥善处理。对于一个简单的测试:
我的文字配色方案为Ragnarok Grey。
即使清除了作业,也似乎保留了对new A()
的引用。 a
语句按预期在using
语句的末尾处理,即使它已在内部被删除。
在某些版本的Visual Studio中,这可能会导致Compiler Warning (level 2) CS0728:
可能错误地赋值给本地'a',这是using语句或lock语句的参数。处理呼叫或解锁将发生在本地的原始值上。
using (var a = new A())
{
a = null;
}
以上代码无法编译。您不允许首先分配到using
变量。上面的代码产生了这个编译错误:
无法分配给'a',因为它是'使用变量'
当在只读上下文中发生对变量的赋值时,会发生此错误。只读上下文包括 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变量可以帮助您摆脱困境。