开发者

Why variable that declared in a using statement treated as readonly?

why variable (myform) in using block treated as read-only and the compiler raise an error when I try to pass i开发者_开发问答t as a reference to a function.

sample code:

using (Form myform = new Form)
{
    myfunc(ref myform);
}

passing using variable to a function as ref will raise an error. thus the code above will raise an error.

Note : 'readonly' keyword is unrelated to my question.


I'm looking at an (outdated?) spec [1] right now.

15.13 says that variables that you declare in the resource acquisition part are readonly. That is:

var form = new Form1();
using (form) {
    form = null;
}

works, but

using (var form = new Form1()) {
    form = null;
}

doesn't. This answers part of the question (i.e. Why? Because it is part of the spec..), but I understand that this is not really satisfying. But why would you even want to do that?


Edit: After thinking about this, let me offer a possible explanation for this rule:

You have

using (var something = new Foo()) {
   something = /* whatever */
}

and the compiler allows this. Now what if Foo needs a lot of unmanaged resources (maybe that's the reason you wanted to use using in the first place)? After the using block you have no way to access this reference anymore. It wasn't disposed, because you reassigned something and forgot to handle it yourself. You don't have a guarantee that the GC runs, at all. Or when. You just created a resource leak that is obscured and hidden.


A final one, inspired by Henk's link to Eric Lippert's blog, which again just ends up throwing the spec at us:

A using statement of the form

using (expression) statement

has the same two possible expansions, but in this case ResourceType is implicitly the compile-time type of the expression, and the resource variable is inaccessible in, and invisible to, the embedded statement.

In other words:

var form = new Form1();
using (form) {
    form = null;
}

works, because this is expanded to

var form = new Form1();
var invisibleThing = form;
try {
   form = null;
} finally {
    if (invisibleThing != null) ((IDisposable)invisibleThing).Dispose();
}

So in this case the fact that you have no influence over the using reference is just hidden from you and is exactly like in the previous case.

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


If you mean the variable instantiated at the start of a using block, then it's read only because it needs to be disposed at the end of the block. The point of a using block is to have a resource destroyed in a predictable way rather than waiting for the garbage collector to do it's job.


First of all, in your example there is most likely no reason for the ref modifier.

So you're asking a very theoretical question, it never is a problem in practice.

The annotated C#3 manual does not give an explanation.

Eric Lippert touches on the subject in a post about (not) Boxing in a using statement.

My own stab at it:

The compiler makes the controlled var readonly because it can. Leaving this var writeable would open up even more cans of worms, see the Boxing article from Eric. Note that a similar rule applies to the enclosed variable in a foreach(). Basically, writing to these vars would never be useful, so the compiler takes maximum control over them.


readonly is a keyword in C#. It's useful when you want to ensure the value never changes outside a constructor.

This keyword could be helpful when you're contributing code to a large project and you're worried coworkers might try to change a variable that should never be altered.

Edit: I'm curious why someone downvoted my answer. Whoever downvoted can you please show my where my answer is wrong? Thanks.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜