I can decide to make something in my code exceptional, sure. I can't decide to make something in the library not-exceptional, though.
You can put try-catch everywhere or nowhere (or choose a reasonable place in between).
This isn't always the case. Sometimes the only way to answer a question ("Can this string be parsed as an integer?") is to try it and catch the exception. And there's just no way to do that coherently without catching it immediately.
Later releases of .NET do include a non-exception-throwing TryParse() call in many places. I'm pretty sure I've run into some cases where that was not available, however, and I'm pretty sure I've run into similar situations in other methods besides Parse(). And TryParse() was a late addition; look back in the 1.1 or 2.0 docs, and it doesn't exist.
In other words, somebody thought it was reasonable to force .NET users to catch some exceptions immediately.
Your hands are not tied by .net exceptions...
No, but there's not much point in using .NET if I'm not using the library that comes with it. And the design of the library does tie my hands in some cases.
I think the author makes a great point about libraries that use exception handling blurring the line between bugs and expected problems. That's exactly how I feel about the C# work I've done.
> I can decide to make something in my code exceptional, sure. I can't decide to make something in the library not-exceptional, though.
Making something in the library non-exceptional is equivalent to discarding an error. Catch the exception and discard it. Done. Do this at whatever level you feel is appropriate (or don't, and handle the exception in a more reasonable fashion).
> In other words, somebody thought it was reasonable to force .NET users to catch some exceptions immediately.
What do you suppose should be done? The other option seems to be to continue in a erroneous state. I'm probably not familiar with every possible error-handling methodology, but it seems the main ones are "error codes" (those worked so great in C, right), "exceptions" (annoying, but error handling in general is annoying), and "injected handling" (where the caller can inject error handling code somehow; but this is more complicated and requires deeper knowledge about the callee). Is there a better option?
> No, but there's not much point in using .NET if I'm not using the library that comes with it. And the design of the library does tie my hands in some cases.
My point is that you are not tied by .Net any more than you are tied by any other exception-handling language. You can handle exceptions where and how you feel is appropriate.
> I think the author makes a great point about libraries that use exception handling blurring the line between bugs and expected problems. That's exactly how I feel about the C# work I've done.
I think this is a bit of a red herring. An exceptional condition is simply a special case. A bug in the code is an exceptional condition. A problem parsing a number is an exceptional condition. Modern languages generally have specific exceptions to allow you to handle different situations with custom logic, but it's important to note that the runtime can't reliably distinguish between "bugs" and "expected problems". Did your number parsing fail because the user entered an invalid value or because your code grabbed column 3 instead of 4?
Making something in the library non-exceptional is equivalent to discarding an error ... The other option seems to be to continue in a erroneous state.
I guess this is where we differ. I feel that the designers of the .NET library have chosen to throw exceptions in places where nothing exceptional is actually happening, where no error has occurred, where the programmer may very well be expecting the "exceptional" outcome.
Where my code must handle such conditions, forcing me to handle them as exceptions makes my code longer, less readable, harder to change, and harder to reason about.
...it's important to note that the runtime can't reliably distinguish between "bugs" and "expected problems".
This is exactly what the author of the linked piece points out, this is a part of my complaint, and it's an issue Microsoft has tacitly acknowledged the seriousness of by the addition of alternatives to exception-throwing calls, like TryParse().
The problem from my perspective isn't the runtime or the languages that target it, but choices made when the library was designed.
It does not feel to me, as a user of these massive libraries, that there was any systematic way of deciding what should be and what should not be reported as an exception.
> I guess this is where we differ. I feel that the designers of the .NET library have chosen to throw exceptions in places where nothing exceptional is actually happening, where no error has occurred, where the programmer may very well be expecting the "exceptional" outcome.
When does this actually happen? Are you really expecting it to fail when you open a file, or when you parse an integer, or whatever else? Where is .Net throwing exceptions in cases that no error has occurred and that you expect?
This complaint is common, but it feels rather hollow to me. Most of the time it seems to come down to a preference for error codes over exceptions, or an annoyance with the try-catch boilerplate, rather than a legitimate complaint about exceptions being thrown inappropriately.
> Where my code must handle such conditions, forcing me to handle them as exceptions makes my code longer, less readable, harder to change, and harder to reason about.
Are you suggesting that every function should have two versions like Parse and TryParse? Is this really what you'd prefer the .Net team work on, instead of providing new tools and functionality? Or are you wanting something like "ON ERROR RESUME NEXT" so that you can ignore these "expected" errors?
> This is exactly what the author of the linked piece points out, this is a part of my complaint, and it's an issue Microsoft has tacitly acknowledged the seriousness of by the addition of alternatives to exception-throwing calls, like TryParse().
Eh, the linked piece seemed mostly to be pining for the days of error codes. There's no general way to determine if a failure is a "bug" or "expected", not for exceptions and not for anything else. If you want to avoid exceptions for "expected" failures, then you're asking for no exceptions at all, which is fine, but the problem isn't just the definition of "exceptional".
> It does not feel to me, as a user of these massive libraries, that there was any systematic way of deciding what should be and what should not be reported as an exception.
The systematic way was "it's exceptional if it's not the desired or expected outcome". The addition of TryParse was a nice bonus, but is in itself an exception to the exception model.
Can you give me a practical situation where an exception is thrown despite there not being an error, aside from the canonical Integer.Parse() example? In my experience, that's not the bulk of any practical program, and it's still exceptional from the point of view of the Parse function.
I'd be interested in discussing this, but I'm not really sure what you think would be an improvement. And yes, it's a rather uphill battle if your proposal is to use error codes most of the time. I think that ship already sailed (although there's a strong case for error codes in C++, but that's kind of a special case).
However, in the interest of trying to be helpful, my guess is that you have a bug in your app that plays poorly with a bug in Win32. A quick search for BufferedGraphicsContext.CreateCompatibleDIB yielded this question on SO (link to top answer) which indicates a resource leak may be at fault:
I can decide to make something in my code exceptional, sure. I can't decide to make something in the library not-exceptional, though.
You can put try-catch everywhere or nowhere (or choose a reasonable place in between).
This isn't always the case. Sometimes the only way to answer a question ("Can this string be parsed as an integer?") is to try it and catch the exception. And there's just no way to do that coherently without catching it immediately.
Later releases of .NET do include a non-exception-throwing TryParse() call in many places. I'm pretty sure I've run into some cases where that was not available, however, and I'm pretty sure I've run into similar situations in other methods besides Parse(). And TryParse() was a late addition; look back in the 1.1 or 2.0 docs, and it doesn't exist.
In other words, somebody thought it was reasonable to force .NET users to catch some exceptions immediately.
Your hands are not tied by .net exceptions...
No, but there's not much point in using .NET if I'm not using the library that comes with it. And the design of the library does tie my hands in some cases.
I think the author makes a great point about libraries that use exception handling blurring the line between bugs and expected problems. That's exactly how I feel about the C# work I've done.