Nested Using Statements
I got a comment on the language feature post, asking about an easier way to write:
using (StreamWriter w1 = File.CreateText("W1"))
{
using (StreamWriter w2 = File.CreateText("W2"))
{
// code here
}
}
You can do this by writing:
using (StreamWriter w1 = File.CreateText("W1"))
using (StreamWriter w2 = File.CreateText("W2"))
{
// code here
}
Comments
- Anonymous
August 05, 2004
Eric,
Can't you also do this:
using (StreamWriter w1 = File.CreateText("W1"), w2 = File.CreateText("W2"))
{
}
(If, and only if, both objects are of the same type).
Incidently, why is this syntax supported, but restricted to cases where both have the same type? - Anonymous
August 05, 2004
That's cool, but I prefer the first way for several reasons.
Firstly, it's easier to read the first snippet. Also, the first snippet clearly defines the context of each using statement, whereas the second could lead to ambiguity for someone who is not familiar with this syntax. - Anonymous
August 05, 2004
real programmers just expand the whole thing out with a huge monolithic sequence of try finallys.
(I'm kidding. Really.) - Anonymous
August 05, 2004
John: I can't tell you why the syntax was decided in this way, however I can explain why it works that way.
The grammar for using is defined as:
using-statement:
using ( resource-acquisition ) embedded-statement
resource-acquisition:
local-variable-declaration
expression
A local-variable-declaration is the same syntax you use to declare variables, with the same rules applied
int x;
double y,z;
Thus, the using statement can have multiple variables of the same type just as a variable declaration can.
Mixing types makes for more difficult grammar, consider situations where you want to do int x, y; and double a,b;
the equivilent using statement would be
using (int x, y, double a, b)
which is strange and unheard of in the rest of the language. - Anonymous
August 05, 2004
Thanks Daniel.
>the equivilent using statement would be
>using (int x, y, double a, b)
I guess I'm wondering why something like this is not supported:
using (int x, y; double a, b)
(I just changed one of your commas to a semi-colon.)
Presumably because it doesn't really offer much benefit (other than a bit more brevity) over the solution Eric originally posted. - Anonymous
August 05, 2004
Thanks for the post, Eric. I think I learn something new every day reading blogs. And I wouldn't have learned about this if I didn't ask. I think I like that syntax better than I was suggesting in the language post, and what John Rusk is asking here. With our suggestion one could write something like this:
using( ResourceA a = ...;
ResourceB b = ....;
ResourceC c = ...;
etc.
){
//do stuff
}
which hampers readability. With the current syntax you can see right away every one of them. Too bad I haven't seen any code examples like this. - Anonymous
August 05, 2004
The comment has been removed - Anonymous
August 05, 2004
I've always wondered why the language designers wanted 'using' to work like a control-flow statement (like while, if, etc.), because it doesn't control any flow.
I would have liked it better as a declaration specifier like this:
using StreamWriter out = File.CreateText(...);
which would inject the name 'out' in the current scope instead of opening a new one.
I guess that's just the C++ programmer in me talking... Which reminds me that the new C++/CLI will soon have this feature anyway so I won't complain about C# not having it :). - Anonymous
August 05, 2004
The comment has been removed - Anonymous
August 05, 2004
Nested using statements can soak up a lot of indentation so Eric Gunnerson has posted a tip on how to code them more succinctly. Taking his example, instead of this: using (StreamWriter w1 = File.CreateText("W1")) { using (StreamWriter w2 =... - Anonymous
August 05, 2004
This is great! It's a lot easier to read than indented using statement.
Thanks,
Sean
...more discussion
http://blog.magenic.com/seans/archive/2004/08/06/261.aspx - Anonymous
August 05, 2004
RE: Pointing a delegate to a property...
I don't think this is possible, primarily due to the language grammar. As you mentioned, the C# compiler doesn't like you referring to the underlying get_ and set_ methods, primarly because these methods are marked as "special" (I forget the actual IL opcodes; it's probably specialname or something).
Since you can't refer to the methods directly, you'd have to directly use the Property. Alas, in the C# language grammar merely referencing a Property is identical to invoking the get_ function.
For example, with methods:
// this works
MyDelegate d = new MyDelegate (this.MyMethod);
// this doesn't; MyMethod() is invoked.
MyDelegate e = new MyDelegate (this.MyMethod());
A property reference outside of assignment context implicitly invokes the get_ method, so:
// error; similar to previous method example
MyDelegate f = new MyDelegate (this.Property);
// above implicitly identical to non-C# code:
MyDelegate g = new MyDelegate (this.get_Property());
So, what do you do? In C# 1.1, you add a helper method which can be used by the Delegate.
In C# 2.0, you could use an anonymous delegate:
// C# 2.0: getter
MyDelegate h = delegate {return this.Property;};
// C# 2.0: setter
MyDelegate i = delegate (int value) {this.Property = value;};
It's still not ideal, but at least there's less typing.
- Jon - Anonymous
August 06, 2004
Just a side note, I've added a link to Jonathan's comment from my feedback request FDBK13230 (regarding property delegates) on MSDN. In hindsight I should have added it as a proposed solution, but I'm still getting used to using their feedback site, and it doesn't really agree with my browser half the time.
http://lab.msdn.microsoft.com/ProductFeedback/viewFeedback.aspx?FeedbackId=e9496dee-5fab-41eb-882c-247898daa19d - Anonymous
August 06, 2004
While yes, this does work, it's generally considered bad programming practice in the sense of readability to not use braces in these instances. - Anonymous
August 08, 2004
John: No that syntax won't work, mainly because of the definition of local-variable-declaration, but there are semantic issues as well. By allowing an arbitrary number of semicolons I imagine the resource-acquisition section would get confusing quickly since one could do
using(X x = Mymethod(); Y y = AnotherExpression; Q q = v; V r = 7;)
which is really more of a block, I think.
Stéphane: I implemented such a feature experimentally in mono at one point. It worked but the average lifespan of an object would go up a bit and it made varaible declaration a bit messy(variables had to be declared all through the body, even if they didn't make sense to). Also, since there was no clear way to know when to create a copy of the value, the variables were effectivly read-only. Because they were read only there was no easy way to create a variable and then assign to it conditionally. It convinced me that the using statement was probably a better choice, its at the least less surprising. - Anonymous
August 09, 2004
re: why not have using decorate variables...
I have been asking for this for a year.
Why not have a using on a variable declaration, which promotes the IDispose behavior to the enclosing scope - and if it's called something other than "using" that's fine ;^)
public void SomeMethod() {
using IDbConnection conn = GetDbConnection();
// ...
}
...yeah, a name like "disposable" would fit better too...