为什么变量(myform)在使用块中被视为只读并且当我尝试将它作为对函数的引用传递时编译器会引发错误。
示例代码:
using (Form myform = new Form)
{
myfunc(ref myform);
}
将 using 变量作为 ref 传递给函数将引发错误。因此上面的代码会引发错误。
注意:“只读”关键字与我的问题无关。
为什么变量(myform)在使用块中被视为只读并且当我尝试将它作为对函数的引用传递时编译器会引发错误。
示例代码:
using (Form myform = new Form)
{
myfunc(ref myform);
}
将 using 变量作为 ref 传递给函数将引发错误。因此上面的代码会引发错误。
注意:“只读”关键字与我的问题无关。
我现在正在查看(过时的?)规范 [1]。
15.13 说你在资源获取部分声明的变量是只读的。那是:
var form = new Form1();
using (form) {
form = null;
}
有效,但是
using (var form = new Form1()) {
form = null;
}
没有。这回答了部分问题(即为什么?因为它是规范的一部分..),但我知道这并不令人满意。但你为什么还要这样做呢?
编辑:考虑到这一点,让我对此规则提供一个可能的解释:
你有
using (var something = new Foo()) {
something = /* whatever */
}
并且编译器允许这样做。现在,如果 Foo 需要大量非托管资源怎么办(也许这就是您想首先使用的原因using
)?在 using 块之后,您将无法再访问此参考。它没有被处理掉,因为你重新分配something
并忘记了自己处理它。您根本无法保证 GC 会运行。或者什么时候。您刚刚创建了一个被掩盖和隐藏的资源泄漏。
最后一个,灵感来自 Henk 对 Eric Lippert 博客的链接,它再次向我们抛出了规范:
形式的使用语句
使用(表达式)语句
具有相同的两种可能的扩展,但在这种情况下,ResourceType 隐含地是表达式的编译时类型,并且资源变量在嵌入语句中是不可访问的,也不可见。
换句话说:
var form = new Form1();
using (form) {
form = null;
}
有效,因为这已扩展到
var form = new Form1();
var invisibleThing = form;
try {
form = null;
} finally {
if (invisibleThing != null) ((IDisposable)invisibleThing).Dispose();
}
因此,在这种情况下,您对参考没有影响的事实对您using
来说是隐藏的,并且与前一种情况完全相同。
1:http://www.ecma-international.org/publications/standards/Ecma-334.htm
如果您的意思是在 using 块的开头实例化的变量,那么它是只读的,因为它需要在块的末尾处理。using 块的目的是以可预测的方式销毁资源,而不是等待垃圾收集器完成它的工作。
首先,在您的示例中,很可能没有理由使用ref
修饰符。
所以你问的是一个非常理论的问题,在实践中从来都不是问题。
带注释的 C#3 手册没有给出解释。
Eric Lippert 在一篇关于(不是)拳击的文章中谈到了这个主题。
我自己的刺:
编译器使受控 var 只读,因为它可以。让这个 var 可写会打开更多的蠕虫罐,请参阅 Eric 的拳击文章。请注意,类似的规则适用于 a 中的封闭变量foreach()
。基本上,写入这些 var 永远不会有用,因此编译器会最大限度地控制它们。
readonly是 C# 中的关键字。当您想确保值永远不会在构造函数之外更改时,它很有用。
当您为大型项目贡献代码并且您担心同事可能会尝试更改不应更改的变量时,此关键字可能会有所帮助。
编辑:我很好奇为什么有人反对我的回答。谁投了反对票,你能告诉我我的答案哪里错了吗?谢谢。