C# 为什么using语句中声明的变量被视为只读?

C# 为什么using语句中声明的变量被视为只读?,c#,.net,using-statement,object-lifetime,C#,.net,Using Statement,Object Lifetime,为什么使用被视为只读的变量?它是c语言规范还是托管语言规范?这是因为c#是一种.net语言?提前谢谢 注意:using variable是出现在using语句中的变量 示例代码: using (Form s = new Form) { myfunc(ref s); } 我们无法在using块中更改using变量的值。该代码将引发错误。 注意:我不想你讨论只读关键字。是C#中的一个关键字。当您希望确保值在构造函数之外不会更改时,它非常有用 当您为一个大型项目贡献代码并且担心同事可能试图更

为什么
使用被视为只读的
变量?它是c语言规范还是托管语言规范?这是因为c#是一种.net语言?提前谢谢

注意:using variable是出现在using语句中的变量

示例代码:

using (Form s = new Form)
{
    myfunc(ref s);
}
我们无法在using块中更改using变量的值。该代码将引发错误。

注意:我不想你讨论只读关键字。

是C#中的一个关键字。当您希望确保值在构造函数之外不会更改时,它非常有用

当您为一个大型项目贡献代码并且担心同事可能试图更改一个永远不应该更改的变量时,这个关键字可能会很有用


编辑:我很好奇为什么有人否决了我的答案。不管谁投了反对票,你能告诉我我的答案哪里错了吗?谢谢。

如果您指的是在using块开始时实例化的变量,那么它是只读的,因为它需要在块结束时进行处理。使用块的要点是以可预测的方式销毁资源,而不是等待垃圾收集器完成它的工作。

首先,在您的示例中,很可能没有理由使用
ref
修饰符


所以你问的是一个非常理论化的问题,在实践中从来都不是问题

带注释的C#3手册没有给出解释

埃里克·利珀特在一篇博文中谈到了这个问题

我自己也这么想:

编译器使受控变量为只读,因为它可以。让这个变量可写将打开更多的蠕虫罐头,请参阅Eric的拳击文章。请注意,类似的规则适用于
foreach()
中的封闭变量。基本上,写入这些变量永远不会有用,因此编译器会对它们进行最大程度的控制。

我现在正在查看一个(过时的?)规范[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
的原因),该怎么办?使用块后,您将无法再访问此引用。它没有被处理,因为您重新分配了
某些内容
,却忘了自己处理它。你根本不能保证GC运行。或者什么时候。您刚刚创建了一个隐藏的资源泄漏


最后一个,灵感来源于Henk与Eric Lippert博客的链接,该链接再次向我们抛出了规范:

表单的using语句

使用(表达式)语句

具有相同的两个可能扩展,但在本例中,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();
}
因此,在本例中,您对使用
引用的
没有任何影响这一事实对您是隐藏的,并且与前面的情况完全相同


1:http://www.ecma-international.org/publications/standards/Ecma-334.htm

呃,有什么问题吗?我无法理解……我认为这应该留在
使用问题中。重复我前面的问题:在什么情况下这会有用,而不会增加不必要的混淆(这可能用try/finally处理得更好)。在出现使用场景之前,围绕“原始值”/“最终值”(以及如何处理)的复杂性问题使它变得愚蠢。这是一个合法的问题,而前一个问题偏离了另一个方向。@Henk我不确定它是否这样做;在我看来,答案与我的回答基本相同。在这个问题有任何意义之前,我的投票结果是从后面进行的(见我之前的评论)。因为它不再适用,我不知道为什么其他4个人在很久以后同意了我的观点。投票重新打开。但只有在using块中声明它时,它才是只读的。一个预先声明的变量不会变成只读的。@Henk好吧,如果它没有在那里声明,那将是一个完全不同的场景;计算赋值表达式的结果。在这方面没有使用变量(至少可用)来讨论/对比scenario@Marc当前位置我想,这项作业并不重要。使用(var)
特殊处理
确实是第三种情况。“所以你问的是一个非常理论化的问题,在实践中从来都不是问题。”我知道。如果我更改变量的引用,垃圾收集器可以释放该变量。我不明白为什么c不允许我们更改被视为使用变量的一次性对象的引用。@LightWing在使用
时使用
,您是在声明该对象的预期寿命。如果您想更早地将其设置为空(顺便说一句,这不太可能使它更快地被收集),请使用try/finallyThanks作为链接,Henk。我想解释就在那里。最后一次更新了我的答案,虽然现在问题已经结束,但你的答案没有错。结果证明这无关紧要。提问者后来对问题进行了编辑(当然是在5分钟的时间内,因此在编辑历史记录中没有记录),结果显示他所说的是使用
语句的
,而不是结合常规变量的
只读
关键字。(不是我的反对票,但既然你问了……不用担心,我在问题澄清之前犯了同样的错误。)已经发布