Req13: Catches in Using blocks


[This post is part of a series, “wish-list for future versions of VB“]


 


IDEA: Allow Catch statements in Using blocks. A Using block is just a Try/Finally block that calls “Dispose” in its destructor. It’d be handy if you could stick “Catch” statements inside the Using block as well. In other words, this code


        Using x As New C


            ….


        Catch ex As System.IO.FileFormatException


            ….


        End Using


would be shorthand for this:


        Dim x As New C


        Try


            ….


        Catch ex As System.IO.FileFormatException


            ….


        Finally


            If x IsNot Nothing Then


                x.Dispose()


            End If


        End Try


 


Provisional evaluation from VB team: it’s a decent idea, one worth considering against the other desirable features. What do you think? Does it provide enough benefit to be worth adding to the language?


 

Comments (10)

  1. Dzonny says:

    Should it be shorthand for

    Dim f = IO.File.Open(…)

    Try

       …

    Catch ex As IO.IOException

       …

    Finally

       If f IsNot Nothing Then DirectCast(f, IDisposable).Dispose

    End Try

    or

    Dim f As IO.FileStream

    Try

       f = IO.File.Open(…)

       …

    Catch ex As IO.IOException

       …

    Finally

       If f IsNot Nothing Then DirectCast(f, IDisposable).Dispose

    End Try

    ?

    This is important difference and I vote for the second version because now catchingexceptions in Using "header" is very difficult and leads to ugly code (whole Using enclosed io Try-Catch).

  2. Jonathan Allen says:

    If it isn’t hard, please do this. I find myself using that pattern a lot.

  3. Matt Higginbotham says:

    +1 from me.. I would love to see this feature.

  4. Kevin Ryall says:

    Definitely a ‘nice to have’ feature – it’s quite a common use case.

  5. Damien says:

    Yup. It’s simple, logical, and reduces indentation (especially if you have multiple nested usings, and you currently are nesting those within Try/Catch blocks.

  6. MH Lim says:

    Back in the days when C# has "using" but VB didn’t, I had hoped for this

    Try Using d As New DisposableObject

       …

    Catch ex As Exception ‘// Optional

       …

    Finally ‘// Optional

       …

    End Try

    To me the syntax properly indicate that the operation could fail, and if it does, we have the option to catch the exception and/or do any cleanup. The beauty of it (to me at least :-)) is we are reusing the common Try…End Try construct.

    Now I would consider a "Use" keyword ala F#

    Sub MethodA

       Use d1 As New DisposableObject

       …

       Try

           Use d2 As New DisposableObject

           …

       Catch ex As Exception

           …

       Finally

           …

       End Try ‘// d2 is disposed here

    End Sub ‘// d1 is disposed here

  7. MH Lim says:

    Oh.. I failed to mention both Use and Using can coexist.

    Given a choice between Using/Catch and Use, I’d prefer Use, as I see Using block more of a resource management construct than an error handling construct. Mixing Using/Catch and Try/Catch in the same method body probably isn’t a good idea (Try Using/Catch would be a different story though :-))

  8. Kyralessa says:

    While I don’t think I’d use it all over the place, this would be a handy feature to have for those occasions when I did use it.

  9. Jeff says:

    A small advantage C# has over VB with using/Using is the ability to nest multiple usings without using extra braces:

    using x

    using y

    using z

    {

       // …

    }

    Could we perhaps have an equivalent in VB? It could look like this:

    Using x, y, z

       ' …

    End Using

    Each "argument" would be in scope for the declaration/initialization of the next, just like with nested Usings today. The advantage would be that we could avoid three-layers deep indentation when performing a simple SQL query, for instance.

  10. Hey Jeff, the syntax you ask for is ALREADY in VB! Like this:

    Dim request = HttpWebRequest.Create("http://microsoft.com")

    Using response = request.GetResponse(),

       stream = response.GetResponseStream(),

       reader = New StreamReader(stream)

       Console.WriteLine(reader.ReadToEnd)

    End Using