Empty Catch Blocks



  • Continuing the discussion from Obfuscation, yo:

    @Arantor said:

    What's the prevailing opinion on a try/catch block with nothing in the catch?

    When is it ok to have empty catch blocks?



  • Only if you use the following comment:

    //Omnomnom

    ...
    On a more serious note, I sometimes use them when I'm using tasks/threadpools that have a potential to fail, but I don't want the issue bubbling up if there's a problem (usually for long polling tasks, that sometimes have items that no longer exist or a database hiccup, or whatever. The issue is non fatal and usually self healing, but can throw a large number of exceptions due to the type of polling it's doing)



  • I use them for loading optional config values from app.config. Pseudo code, too lazy to look up syntax.

    try {
        this.intOption = int.Parse(ConfigurationManager.AppSettings["intOption"])
    } catch (Exception) {}
    

    Similar for Dates, enums etc...



  • @chubertdev said:

    When is it ok to have empty catch blocks?

    In general, when you don't care if the error happened or not. For example, when a multi-threaded application is closing and it sometimes craps out with an UI exception, you can pretty much safely ignore it.


  • Discourse touched me in a no-no place

    I use them only when I know that all the failure modes that hit the empty block leave things in a sane state (typically because the variable that's possibly being assigned to inside things has a sensible default assigned beforehand). I also put a comment in to the effect that I know that the catch can be hit and the exception silently swallowed.

    I try to avoid it though. It's usually more confusing than it's worth.


  • Trolleybus Mechanic

    @dkf said:

    I use them only when I know that all the failure modes that hit the empty block leave things in a sane state

    This.

    Essentially, it might be justified when you know you'll be dealing with a valid state - although signalled in an unfortunate fashion - and checking to prevent exceptions would impose a greater performance hit than throwing them out into the ether.

    @dkf said:

    I also put a comment in to the effect that I know that the catch can be hit and the exception silently swallowed.

    I try to avoid it though. It's usually more confusing than it's worth.

    +1

    'Coz I can only like a post once.



  • @Maciejasjmj said:

    In general, when you don't care if the error happened or not. For example, when a multi-threaded application is closing and it sometimes craps out with an UI exception, you can pretty much safely ignore it.

    So on something like that, do you try to catch one or more specific exception types?



  • @chubertdev said:

    So on something like that, do you try to catch one or more specific exception types?

    I tend to catch specific ones - after all, if my SetText() procedure fails with a DivisionByZeroException, I assume I'd like to know that.



  • @Maciejasjmj said:

    I tend to catch specific ones - after all, if my SetText() procedure fails with a DivisionByZeroException, I assume I'd like to know that.

    Why would you try to catch an arithmetic exception for that type of method, instead of something like NullReferenceException? Would it be based on precedence of that type of exception occurring?



  • @chubertdev said:

    Why would you try to catch an arithmetic exception for that type of method, instead of something like NullReferenceException? Would it be based on precedence of that type of exception occurring?

    I assumed he meant he'd catch the expected type, and let the unexpected one bubble up.



  • Uh, I wouldn't. I would let it bubble up to the development environment and fix my code, because it's not what I expect from that method.

    As for what I would catch, ObjectDisposedException was the one I needed to handle the last time.



  • @GOG said:

    +1

    'Coz I can only like a post once.

    Liked that for you.


  • Trolleybus Mechanic

    Cheers!



  • @Maciejasjmj said:

    Uh, I wouldn't. I would let it bubble up to the development environment and fix my code, because it's not what I expect from that method.

    As for what I would catch, ObjectDisposedException was the one I needed to handle the last time.

    Got it, misinterpreted your post.



  • That link is crazy,

    They open a memory stream
    Close it (not dispose)
    Try to read from it
    Catch an 'object disposed' exception block
    And the annotation specifically states the return error message is 'Cannot access a closed Stream.'

    Why is a closed stream filed under a disposed object in this instance? Is it just because of how they accessed the original stream, or is this across the board?

    I'd expect an error more along the lines of a 'StreamClosedException' / 'StreamReaderException' (or maybe 'endofstreamexception'/'constraintexception'/'indexoutofrange', though each has it's own issues in this context)

    Anybody have more info on why they chose object disposed?



  • @Matches said:

    Anybody have more info on why they chose object disposed?

    I'm guessing that it's easier to determine that an object of unknown type was disposed than to try to figure out what's wrong with the specific type of object that was disposed.



  • Granted, but they've already determined (per the annotation) that the stream is closed. I feel like there's a fairly big difference between a closed object and a disposed one. (Unless it's a closed object with a null value, in which case GC could easily turn that into a disposed object, which is what I was wondering happened here.)



  • @Matches said:

    Granted, but they've already determined (per the annotation) that the stream is closed. I feel like there's a fairly big difference between a closed object and a disposed one. (Unless it's a closed object with a null value, in which case GC could easily turn that into a disposed object, which is what I was wondering happened here.)

    I'm assuming that "disposed" and "collected" are separate things, but I'm not an expert on garbage collection.



  • This method calls Dispose, specifying true to release all resources.

    So, yeah. A bit of a WTFy example, but the framework works as you'd expect.



  • I imagine that the Dispose() method doesn't remove the object from memory, only marks it as disposed, so your can can't touch it, and the only thing that should is the garbage collector. It's still in memory until the garbage collector decides that it's an optimal time to remove it.



  • facepalm

    So much for calling .Close(), .Dispose() then. (Though to be fair, I use using(...){} wherever possible)

    That seems a bit wonky when so many other things explicitly requiring .dispose()



  • @Matches said:

    So much for calling .Close(), .Dispose() then. (Though to be fair, I use using(...){} wherever possible)

    That seems a bit wonky when so many other things explicitly requiring .dispose()

    Yeah, I rarely call either method myself. I pretty much always employ the using design.


Log in to reply