15

Possible Duplicate:
Passing an IDisposable object by reference causes an error?

Why doesn't C# allow passing a variable from a using block to a function as ref or out?

This is my code:

using (Form s = new Form())
{
    doSomthing(ref s);
}

The function ends before the using block ends, why doesn't C# let me pass s as ref or out parameter?

Community
  • 1
  • 1
Saleh
  • 2,982
  • 5
  • 34
  • 59
  • What is the signature of the method `doSomething(...)`? What is the error you're seeing? – Paul Turner May 14 '11 at 09:51
  • Uhm, close voters? Unless I'm totally mistaken the linked question has nothing to do with `using` blocks. – musiKk May 14 '11 at 10:04
  • @Lightwing, i have rolled back your question edit as you removed the code, which removes context from the question and the answers. If you edit your question, please don't remove important stuff and don't morph the question. – slugster May 14 '11 at 10:12
  • **Why using variable treated as readonly**? i think it is not really necessary – Saleh May 14 '11 at 10:19
  • "Why using variable treated as readonly?" - This is another question on top of the existing one. Please ask it as a separate question: http://stackoverflow.com/questions/ask – Paul Turner May 14 '11 at 10:36
  • @ProgrammingHero IMO that is the same question... – Marc Gravell May 14 '11 at 10:39
  • @LightWing a better idea would be to show a situation where it is *genuinely useful* to reassign a `using` variable. Do you have an example of this? (I *don't*, because simply: I can't think of a sane usage of that, that isn't made more complex/ugly by trying to force `using` into it) – Marc Gravell May 14 '11 at 10:42
  • There are many situations where one will create an IDisposable and want to Dispose it *except* in some particular situation. A common example would be in a constructor or factory: if an exception occurs that would prevent the created object from being returned, it should be disposed; if the object will be returned, it should not be disposed. Clearing the 'using' variable would not be the most idiomatic way of preventing the dispose, but it would be helpful to have some means of doing so. – supercat Nov 23 '11 at 18:42

3 Answers3

30

using variables are treated as readonly, as any reassignment is probably an error. Since ref allows reassignment, this would also be an issue. At the IL level, out is pretty-much identical to ref.

However, I doubt you need ref here; you are already passing a reference to the form, since it is a class. For reference-types, the main purpose of a ref would be to allow you to reassign the variable, and have the caller see the reassignment, i.e.

void doSomething(ref Form form)
{
    form = null; // the caller will see this change
}

it is not required if you are just talking to the form object:

void doSomething(Form form)
{
    form.Text = "abc"; // the caller will see this change even without ref
}

since it is the same form object.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Why using variables treated as readonly? – Saleh May 14 '11 at 09:54
  • 3
    @LightWing to avoid confusion: i.e. what happens if you change the value of the variable? what gets disposed? the *original* value? or the *final* value? IMO only the ***original*** value makes sense (you don't even need to capture it, in fact) - so why would you need to reassign it? What *possible* scenario makes it useful to reassign the l-value in a using statement? If you find such a scenario, just use try/finally instead. – Marc Gravell May 14 '11 at 09:57
  • This is a sample code and my code is really not as simple as this. – Saleh May 14 '11 at 10:03
  • 1
    @LightWing: these are the rules of the language. This particular rule, treating `using` scope variables as `readonly`, prevents you from shooting yourself in the foot. If you really want to change the variable, you can do so by avoiding a using block, and disposing the variable in an explicit `finally` block. But I seriously doubt the maintainability of your design, especially if it's more complicated! – Pontus Gagge May 14 '11 at 10:28
  • but any rule has one or more reason. – Saleh May 14 '11 at 10:33
  • @LightWing and I already told you the why... "to avoid confusion". That is a pretty damned good reason. – Marc Gravell May 14 '11 at 10:37
9

The var in a using() statement is considered read-only inside the block. See § 8.13:

Local variables declared in a resource-acquisition are read-only, and must include an initializer. A compile-time error occurs if the embedded statement attempts to modify these local variables (by assignment or the ++ and -- operators) or pass them as ref or out parameters.

But note that this only applies to variables declared as part of the using statement, the following is legal (just not a good idea):

var f2 = System.IO.File.OpenText("");
using (f2)
{
    f2 = null;
}
H H
  • 263,252
  • 30
  • 330
  • 514
1

One reason could be that doSomthing could make s refer to another Form instance than the one we have created. That could introduce a resource leak since the using block would then invoke Dispose on the Form instance that came from the method, and not the one created in the using block.

Fredrik Mörk
  • 155,851
  • 29
  • 291
  • 343