logoalt Hacker News

cogman10yesterday at 3:42 PM1 replyview on HN

You'd write it like this

    void bar() {
      try (var f = foo()) {
        doMoreHappyPath(f);
      }
      catch(IOException ex) {
        handleErrors();
      }
    }

    File foo() throws IOException {
      File f = openFile();
      doHappyPath(f);
      if (badThing) {
        throw new IOException("Bad thing");
      }
      return f;
    }
That said, I think this is a bad practice (IMO). Generally speaking I think the opening and closing of a resource should happen at the same scope.

Making it non-local is a recipe for an accident.

*EDIT* I've made a mistake while writing this, but I'll leave it up there because it demonstrates my point. The file is left open if a bad thing happens.


Replies

mort96yesterday at 3:56 PM

In Java, I agree with you that the opening and closing of a resource should happen at the same scope. This is a reasonable rule in Java, and not following it in Java is a recipe for errors because Java isn't RAII.

In C++ and Rust, that rule doesn't make sense. You can't make the mistake of forgetting to close the file.

That's why I say that Java, Python and C#'s context managers aren't remotely the same. They're useful tools for resource management in their respective languages, just like defer is a useful tool for resource management in Go. They aren't "basically RAII".

show 1 reply