DIP33: A standard exception hierarchy

Jonathan M Davis jmdavisProg at gmx.com
Tue Apr 2 10:46:35 PDT 2013


On Tuesday, April 02, 2013 10:41:04 H. S. Teoh wrote:
> On Tue, Apr 02, 2013 at 01:29:00PM -0400, Jonathan M Davis wrote:
> > On Tuesday, April 02, 2013 17:56:07 Lars T. Kyllingstad wrote:
> > > On Monday, 1 April 2013 at 22:26:39 UTC, Jonathan M Davis wrote:
> > > > In general, I'd strongly suggest having subclasses for the various
> > > > "Kind"s in addition to the kind field. That way, you have the
> > > > specific exception types if you want to have separate catch blocks
> > > > for different error types, and you have the kind field if you just
> > > > want to catch the base exception.
> > > 
> > > Then you'd have two points of maintenance when you wish to add or
> > > remove an error category.
> > 
> > True, but it's also trivial to do. But if we had to decide between
> > basically putting error codes on exceptions and using sub-classes, I'd
> > vote for subclasses in most cases - though errno would need to go the
> > error code in the exception route, since it has different meanings in
> > different contexts and would risk an absolute explosion of exception
> > types anyway; though it should probably be translated to a more
> > meaningful exception based on context with the errno exception being
> > chained to it - which is what you suggest in the DIP IIRC. In general
> > though, I'd favor subclasses, and I don't think that it's all that big
> > a deal to give them each specific error codes when you want the base
> > class to have an error code like you're suggesting.
> 
> [...]
> 
> IMO, errno should be stored as-is in a dedicated ErrnoException. Any
> interpretation of errno thereof should wrap this ErrnoException inside
> another hierarchy-appropriate exception. For example:
> 
> void lowLevelIORoutine(...) {
> if (osRead(...) < 0) {
> throw ErrnoException(errno);
> }
> ...
> }
> 
> void libraryRoutine(...) {
> try {
> lowLevelIORoutine(...);
> } catch(ErrnoException e) {
> if (e.errno == ENOENT) {
> // Chain ErrnoException to FileNotFoundException
> throw new FileNotFoundException(e.msg, e);
> } else if (e.errno == ENOSPC) {
> // Chain ErrnoException to DiskFullException
> throw new DiskFullException(e.msg, e);
> } else {
> // etc.
> ...
> }
> }
> }
> 
> This way, user code can catch IOException rather than ErrnoException,
> but errno is still accessible via .next should the user code want to
> deal directly with errno:
> 
> void userCode() {
> try {
> auto f = File("/some/path/to/file");
> } catch(IOException e) {
> if ((auto f = cast(ErrnoException) e.next) !is null)
> {
> handleErrno(f.errno);
> }
> ...
> }
> 
> I think this would be a good use of the current .next field in
> Exception.

Yes. That seems like a good approach and is essentially what I meant.

- Jonathan M Davis


More information about the Digitalmars-d mailing list