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