Combine "Using" with "With"
Combine "Using" with "With", so that you could write for example:
.WriteLine("This is line one.")
.WriteLine("This is line two.")
Using writer As System.IO.TextWriter = System.IO.File.CreateText("log.txt")
writer.WriteLine("This is line one.")
writer.WriteLine("This is line two.")
I’ve seen this request a few times before and while I’m not unsympathetic there are a few problems. The first is we haven’t been able to come up with a good syntax for it – one that is sufficiently descriptive while being concise and aesthetically pleasing but that still reads well.
“Using With x” doesn’t make sense as a natural sentence which goes against the grain of the language.
Another is how such a feature fits stylistically/philosophically in the language. Like why are Using and With specially, what about Sync Lock? What if I want to Lock on a disposable resource and have it be the implicit receiver of member access? Using With SyncLock, SyncLock With Using? Can I mix any two? Like, is there a notion or pattern in the language of combining blocks this way? We’d want to think through that one too for a bit.
One more thing I thought of, the Using block actually accepts a comma-delimited list of expressions to use in lieu of nesting several Using blocks:Using connection As New SqlConnection(“ConnectionString”), command As New SqlCommand(“SELECT * FROM Table”, connection), reader = command.ExecuteReader() End Using
It’s very unclear how combing With with Using (or using Using with With rather) would work in this situation. While we could restrict it to the simple case we’d prefer not to special case. Alternately we could go for a syntax that applies the Using semantics to a With block, which can only take a single expression, to avoid the issue.
Anyway, I’ll keep pondering it and let you know if we come up with anything – feel free to shout out if you think up and suggestions to these problems.
Anthony D. Green, Program Manager, Visual Basic & C# Languages Team
That's an axample of code where With Using construction would be very useful:
Protected Async Function GetHtmlPageByPost(ByVal Url As String, ByVal Data As Dictionary(Of String, String), Optional ByVal AllowAutoRedirect As Boolean = True) As Task(Of String)
Dim Request As HttpWebRequest = WebRequest.Create(Url)
Dim DataStr As String = String.Join("&", From Kvp In Data Select Uri.EscapeUriString(Kvp.Key) & "=" & Uri.EscapeUriString(Kvp.Value))
Dim BinData As Byte() = Options.SiteEncoding.GetBytes(DataStr)
Dim SetCookie As String
.Method = WebRequestMethods.Http.Post
.AllowAutoRedirect = AllowAutoRedirect
.CookieContainer = CookieContainer
.ContentType = "application/x-www-form-urlencoded"
.ContentLength = BinData.Length
.GetRequestStream().Write(BinData, 0, BinData.Length)
Using Response As HttpWebResponse = Await .GetResponseAsync()
SetCookie = .Headers("Set-Cookie")
If Not String.IsNullOrEmpty(SetCookie) Then CookieContainer.SetCookies(Options.CookieUri, SetCookie)
Using ResponseStream As Stream = .GetResponseStream()
Using Reader As New StreamReader(ResponseStream, Options.SiteEncoding)
Return Await Reader.ReadToEndAsync()
I'd like to see this all constructions without adding With logic (i.e. dotted field access) to Using statemant:
With Using ...
Craig Johnson commented
I opened a Roslyn discussion on With (including Using).
With Using r = New DisposableRequest
"Not sure what makes more sense - to have With, then Using or Using, then With. I think I prefer With first since in my mind I'm saying "With this disposable resource, do this and this and this" instead of "Using this disposable resource and now with that resource do this and this and this." Using is sort of an attribute of the thing we're working with so I think With makes more sense to have first."
Dan Walker commented
I like the "With Using x" nomenclature, personally. If you were to add SyncLock to it I would suggest "SyncLock With Using x". Of course this is only for the special case of a single expression on the using statement.
I also like the idea of allowing the With keyword to have Using-like syntax..
With x As Something = New Something
.Color = Red
However, this does not make it clear that "Something" has to implement IDisposable - as that is not currently a requirement for the With keyword. I wouldn't have a problem with this if the IDisposable requirement were lifted. So if the "Something" type implements IDisposable then call it's Dispose method on End With, however, if it does not implement this interface then treat the With block as any other scope block and just let the variable die.
Also, back on the SyncLock concept - I really don't see the need to integrate it into this With/Using feature. But if you must, then make the editor reorder the words into a standard.. like it already does with default properties: Try typing Public Default Property Orge As String into the IDE.
I think your biggest language issue here is going to be what to do at the end of the code block.
With Using x As New Something
End ' Uh.. what am I ending? End With? End Using?
Maybe we need a new keyword:
Oozing x As Something = Something.Create()
.Color = Blue
Adds too much to language complexity.
"Using With x" seems like the most logical order of the keywords to me.
I was unaware the Using statement supported multiple expressions, so thanks for that! My first instinct is to apply the With only to the first expression in the Using statement, but upon reflection, I think it should be the last expression, as that's the one you're most likely to use inside the block (such as in your example above). This should avoid any special cases.
I don't think "Using With" should be combined with SyncLock, because that does add too much complexity. The SyncLock block could either wrap around the Using With block if you need to include any constructors inside the SyncLock, or it could be placed inside the Using With block otherwise. Also, the statement "Using With SyncLock", while being easy to read, devalues the emphasis on the With.
An alternate suggestion is to allow a "Using With x..." block, so you can have a Using block with and without With.
(Please imagine the code as being properly indented.)