When is it right for a constructor to throw an exception?

Solution 1:

The constructor's job is to bring the object into a usable state. There are basically two schools of thought on this.

One group favors two-stage construction. The constructor merely brings the object into a sleeper state in which it refuses to do any work. There's an additional function that does the actual initialization.

I've never understood the reasoning behind this approach. I'm firmly in the group that supports one-stage construction, where the object is fully initialized and usable after construction.

One-stage constructors should throw if they fail to fully initialize the object. If the object cannot be initialized, it must not be allowed to exist, so the constructor must throw.

Solution 2:

Eric Lippert says there are 4 kinds of exceptions.

  • Fatal exceptions are not your fault, you cannot prevent them, and you cannot sensibly clean up from them.
  • Boneheaded exceptions are your own darn fault, you could have prevented them and therefore they are bugs in your code.
  • Vexing exceptions are the result of unfortunate design decisions. Vexing exceptions are thrown in a completely non-exceptional circumstance, and therefore must be caught and handled all the time.
  • And finally, exogenous exceptions appear to be somewhat like vexing exceptions except that they are not the result of unfortunate design choices. Rather, they are the result of untidy external realities impinging upon your beautiful, crisp program logic.

Your constructor should never throw a fatal exception on its own, but code it executes may cause a fatal exception. Something like "out of memory" isn't something you can control, but if it occurs in a constructor, hey, it happens.

Boneheaded exceptions should never occur in any of your code, so they're right out.

Vexing exceptions (the example is Int32.Parse()) shouldn't be thrown by constructors, because they don't have non-exceptional circumstances.

Finally, exogenous exceptions should be avoided, but if you're doing something in your constructor that depends on external circumstances (like the network or filesystem), it would be appropriate to throw an exception.

Reference link: https://blogs.msdn.microsoft.com/ericlippert/2008/09/10/vexing-exceptions/