6

why variable (myform) in using block treated as read-only and the compiler raise an error when I try to pass it 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.

Saleh
  • 2,982
  • 5
  • 34
  • 59
  • 1
    Eh, what's the question? I am not able to understand it... – Petar Minchev May 14 '11 at 10:44
  • 3
    IMO this should had stayed in the `using` question. To repeat my earlier question: *in what scenario would this be useful*, withou adding unnecessary confusion (that might be better handled with try/finally). Until there is a usage scenario, the complexity issues around "original value"/"final value" (and which gets disposed) makes it silly – Marc Gravell May 14 '11 at 10:45
  • @AtoMerZ - readonly keyword is used for fields. – Petar Minchev May 14 '11 at 10:45
  • Pro tip: Ensure that your question makes sense using the "instant preview" pane **before** submitting it. Editing within the allowed 5 minute window is great for answers, but doesn't work out so well for questions. People are pretty quick about trying to answer (and downvoting, and voting to close, etc.). – Cody Gray - on strike May 14 '11 at 10:46
  • @Peter sorry removed. I tried gave me an error, turns out it wasn't about read my var being readonly... – atoMerz May 14 '11 at 10:47
  • Also (tags) using is not garbage collection... Just sayin' – Marc Gravell May 14 '11 at 10:47
  • 1
    It is a legitimate question, and the previous one got derailed into another direction. – H H May 14 '11 at 10:50
  • 1
    @Henk I'm not sure it did; IMO the answer is pretty much the same as I replied there – Marc Gravell May 14 '11 at 10:53
  • 1
    Marc: Agreed. Except for maybe the 'why' part. I'd like to understand the reasons for the differences (see my answer) in handling these cases as well. I see no point in the intention i.e. the modification of the value, but the underlying reasoning are making my curious. – Benjamin Podszun May 14 '11 at 11:00
  • What the... I dont speak about readonly keyword. – Saleh May 14 '11 at 11:01
  • I mean we can change reference value of using variable. – Saleh May 14 '11 at 11:01
  • @LightWing and I *still* mean: show a genuine use-case. – Marc Gravell May 14 '11 at 11:10
  • Use case or not, I'd buy Eric Lippert a beer for an explanation. Really just as a convenience to prevent yourself from messing up? Or is there something more to it that I fail to see without more coffee? – Benjamin Podszun May 14 '11 at 11:13
  • 2
    My close vote was from back before this question made any sense (see my previous comment). As it no longer applies, I'm not sure why 4 other people agreed with me some time much later. Voting to re-open. – Cody Gray - on strike May 14 '11 at 11:41

4 Answers4

16

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

Benjamin Podszun
  • 9,679
  • 3
  • 34
  • 45
  • 1
    Already posted http://msdn.microsoft.com/en-us/library/aa664736%28VS.71%29.aspx on the other question. – H H May 14 '11 at 11:07
  • 1
    Also, the `using` statement needs the variable in order to be able to call `Dispose` on it. In fact, if you use `using (new Form()){}` the `using` statement will still be able to dispose the form. Apparently it creates its own variable to keep track of the instance. – comecme Jun 25 '12 at 17:43
4

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.

Steve
  • 8,066
  • 11
  • 70
  • 112
  • But it's only read-only if you _declare_ it inside the using block. A pre-declared var does not become readonly. – H H May 14 '11 at 10:53
  • 2
    @Henk well, if it isn't declared there it is a completely different scenario; evaluating the result of an assignment expression. There ***is no*** using variable (available, at least) to discuss / contrast in that scenario – Marc Gravell May 14 '11 at 10:56
  • @Marc: just expression I guess, the assignment isn't crucial. Treating `using(var)` special would indeed be a 3rd scenario. – H H May 14 '11 at 11:05
2

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.

H H
  • 263,252
  • 30
  • 330
  • 514
  • "So you're asking a very theoretical question, it never is a problem in practice." I know. – Saleh May 14 '11 at 10:55
  • Garbage collector can free the variable if i change its reference.i can't understand why c# dont let us to change reference of Disposable Objects that apears as using variable. – Saleh May 14 '11 at 10:57
  • 2
    @LightWing in using `using`, you are making a statement about the expected lifetime of that object. If you want to `null it *even earlier* (which, btw, is unlikely to make it collected any sooner) - use try/finally – Marc Gravell May 14 '11 at 11:01
  • Thanks for the link, Henk. I think the explanation is in there. Updated my answer a final time, although the question is closed now – Benjamin Podszun May 14 '11 at 11:27
1

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.

SquidScareMe
  • 3,108
  • 2
  • 24
  • 37
  • 1
    Your answer isn't wrong. It just turns out that it's irrelevant. Later edits to the question by the asker (within the 5 minute window, of course, so there's no record of it in the edit history) revealed that he was talking about the `using` statement, rather than the `readonly` keyword combined with a regular variable. (Not my downvote, but since you asked... No worries, I made the same mistake before the question was clarified.) – Cody Gray - on strike May 14 '11 at 11:04