Related
In an old blog entry titled Cleaner, more elegant, and harder to recognize, the author states:
In C++ it's not quite so bad because C++ exceptions are raised only at specific points during execution. In C#, exceptions can be raised at any time.
What exactly does he mean by that?
First, I would hesitate to accuse Raymond Chen of confusing anything with anything.
I suspect he means that in C++, exceptions are only thrown where there exists a throw statement. As long as you go deep enough into your code and library functions, you can determine exactly where exceptions may be thrown from. On the other hand, in C# there may be exceptions thrown by the runtime environment at any time. For example, you could get a security exception trying to call any function in any other assembly.
Maybe put it another way:
It is possible in C++ to write functions that offer the nothrow guarantee.
I don't know C#, and I'm pretty sure Raymond Chen does, so I accept his claim that "In C#, exceptions can be raised at any time". Therefore, you cannot write functions in C# that offer the nothrow guarantee.
In C++, nothrow functions are quite an important component of functions that offer the other exception guarantees. To make a strong guarantee (that is, to implement transactions), you usually need something like a nothrow swap, that executes more than one statement without interruption by exceptions. To make a basic guarantee, you need nothrow resource cleanup and you may also need short nothrow stretches of code in which your objects' states violate their class invariants.
Enumerating all the "specific points" in C++ that can throw an exception might be tedious, but in practice it's not that hard to write a short piece of code that definitely doesn't. If you can't do that in C#, that's an important difference.
If Chen's claim about C# is wrong, then it probably doesn't matter what he means. Because he's wrong.
On a full read of the article, I notice that he's mostly talking about example code being incorrect (with obvious implications for real code). So if his C# claim is incorrect due to some special cases of C# code that definitely doesn't throw, but such C# code never appears in tutorial examples, then he would still have an important point about the way the languages are taught -- examples that leave out essential stuff that you need to do to make the example code exception safe are probably bad examples, and they risk teaching bad habits. And unlike with error-code examples, the student (says Chen) can't tell at a glance that the example is bad, and hence might not realise that more work is needed to make them "not-bad".
I think he's talking about asynchronous exceptions, which in C# can be raised in one thread because of something that happens in another. (Note that one of the commenters on Chen's blog entry interprets what he wrote the same way, though unfortunately Chen doesn't respond to that.)
See, e.g., http://msdn.microsoft.com/en-us/library/system.threading.threadabortexception.aspx for an instance where one thread calls the Abort method of an object representing another thread, causing that other thread to get a ThreadAbortException.
He probably means that in C++ exceptions aren't thrown by the framework, but only from your code (or external code written by people who considered their code as "their own code"). In C#, exceptions can happen in the framework as well.
What I don't understand, however, is why the writer seems to prefer having exceptions raised only from your own code.
I have a lot of classes that have been written in C#.NET, and I need to know what exceptions can be thrown by them. How I can do it in Visual Studio 2005.
You pretty much can't. Firstly, .NET/C# don't have checked-exceptions like Java, and secondly there are a number of general exceptions that could happen for any freaky reason.
On a method-by-method basis, you can decorate methods with the exceptions they raise, but this is not guaranteed to be present, accurate or complete.
In general, though, any unexpected* exception should be treated as terminal; just unwind, cleaning up (using) etc as you go and propagate the exception - or at least log it if the operation isn't critical.
*=I'll leave aside the philosophical discussion of whether an exception should every truly be expected as such...
You have to look at the code, it is the only source for this.
It is possible to specify what exceptions can be thrown in xml comments but it is not mandatory, so often this imformation is missing.
Are there any cases when it's a good idea to throw errors that can be avoided?
I'm thinking specifically of the DivideByZeroException and ArgumentNullException
For example:
double numerator = 10;
double denominator = getDenominator();
if( denominator == 0 ){
throw new DivideByZeroException("You can't divide by Zero!");
}
Are there any reasons for throwing an error like this?
NOTE: I'm not talking about catching these errors, but specifically in knowing if there are ever good reasons for throwing them.
JUST TO REITERATE:
I KNOW that in the example I gave you'd probably be better off handling the error. Perhaps the question should be rephrased. Are there any reasons to throw one of these errors instead of handling it at this location.
Let's say you write a library to work with really big integers that don't fit into Int64, then you might want to throw DivideByZeroException for the division algorithm you write.
The .NET runtime is already very good at throwing these exceptions. They are also highly descriptive of what is wrong, you can't add any good commentary to the exception message. "You can't divide by zero" adds no value.
However, you can avoid many of these exceptions by screening the values passed by the client code. You'll want ArgumentNullException with the name of argument if the client code passed a null, ArgumentException when it passed something that is liable to trip DivideByZero.
There is absolutely a reason to do this, and as with most exception throwing questions, you have to think about you as a developer working in a team. What you're writing may be part of another system, or it may be a library or component.
If you write a maths library , and have a function called Divide(int a, int b) that divides them, if someone else wants to use your method and passes in zero, you'll want to throw an exception so they, as a developer, know they've screwed up.
If you don't throw an exception, you introduce bugs into your code. If I used your divide method, and put the values 10 and 0 in, which produces 10/0 and thus an exception, the only correct answer is error. If you decide to change the values so no error occurs, or return 0, that is not what I am expecting - I assume my division worked perfectly, and never notice a problem. I might well take that 0 and go off and use it in other calculations, unaware that it's the wrong answer, because 10/0 is not 0.
You should only use an Exception to handle Exceptional cases.
In this case, it looks like a zero would be invalid user input. You should check for invalid user input and handle it accordingly BEFORE you get to the point that an Exception would be approriate.
As long as you properly handle input, there should be no reason for a DivideByZeroException to happen. If you receive a DivideByZeroException even after validating input...then you know you have a real problem (in which case, the Exception is appropriate).
If you're talking about code that is directly interacting with the UI, then no. I can't think of any reason why you'd want to.
However, if you're building a class/object used by other devlopers and they've passed in data that is clearly stupid then throw the appropriate error during your validation.
If you're writing a BigInteger library, then you absolutely should throw an appropriate DivideByZero exception. If you're writing a shopping-cart library, then...eh, probably not.
I can't, at the moment, think of a good reason to throw a NullReferenceException. If you're create an API with documentation that says "The first parameter to HummingBirdFeeder.OpenSugarWaterDispenser(Dispenser dispenser, int flowRate) is the sugar-water dispenser that you wish to open." And if somebody then comes along and passes a null value to this method, then you should definitely throw an ArgumentNullException.
Letting a NullReferenceException out of your API would just be lazyness, though, because that's wrong and it leaks some of your internals.
EDITED TO ADD:
Now that you changed the question to refer to an ArgumentNullException then the answer is easy: yes, you should definitely throw that kind of exception under these circumstances:
You are writing a public method.
Getting a null value for the argument is in some way inappropriate (i.e., the method makes no sense without that particular argument).
The documentation for the method indicates that null values are not allowed.
In that case, the very first thing your method should do is check for a null value and throw an exception if the condition is violated.
If you are writing a private or internal method, then in most cases you would not need to validate the parameters at runtime in the release build. You can make sure that your own code calls your own code correctly. One thing that helps to create that assurance is to validate the parameters in the debug build by adding assersions:
Debug.Assert(dispenser != null);
This way you can verify that the code is acting correctly and catch any errors earlier without slowing down the released code with a bunch of useless, redundant checks.
In your own code, I doubt there would be much use. However, if you are writing a library that will be consumed by others then you should use exceptions as the means of communicating errors back to the code consuming your library.
"In the Framework, exceptions are used
for both hard errors and logical
errors. At first, it can be difficult
to embrace exception handling as the
means of reporting all functional
failures. However, it is important to
design all public methods of a
framework to report method-failures by
throwing an exception."
Krzysztof Cwalina, Designing Reusable Frameworks
Slightly misleading title here, it is not about throwing the (special) DivideByZeroException but rather the question:
Should I use exceptions while validating user input?
This has probably been asked before. My take: No, just use a flow that lets you handle this with error codes or booleans.
However, when validating 'data' in deeper layers of an app, throwing an exception is usually the right thing to do.
If you were writing a numerical class of some form and can have expected the code calling your class to have performed the validation then I can see it might useful to throw DivisionByZeroException but in almost any other case it would better to check before the operation and throw and ArgumentException or ArgumentOutOfRange exception as appropriate.
NullReferenceException is one of the reserved exceptions that the framework uses that you should never throw through a public API, along with IndexOutOfRange, AccessViolationException and OutOfMemoryException. See the Framework Design Guidelines book or the Code Analysis warning explanation
None that I can think of. I would just program against it. Exceptions can be expensive, so if you can defensively program against it, do that instead of throwing an exception.
At least that's what my senior dev told me when I tried catching a DivideByZeroException many moons ago.
Its a good practice to make these checks at top of the function before you start processing data. Rather then throwing them (or any other method throws these exceptions) in the middle of a method.
In theory (and practice too), identifying and avoiding/eliminating erroneous cases is better than treating them as exceptions. However, it's not always possible to test every case or path through your code - it's also not possible in every case to control your inputs.
A tenet of good design is to have your program recognize and gracefully handle exceptional situations. Furthermore, it's a good idea to provide your users (and ultimately yourself) enough information to diagnose errors - particularly those that can occur after your code is deployed. Therefore, it does sometimes make sense to throw exceptions such as the kind illustrate if it will make your application code more robust and easier to diagnose.
Never (the user will never send 0 as the denominator) and always (the user will always provide appropriate argument values) are dangerous ideas to include in your code. A very small percentage of us program alone, on code that will never be modified or called by another developer. So, we need to write defensive code. In the case of division by zero, I should not be deciding what the appropriate result should be, that falls back on the caller. Throwing the exception seems like a reasonable way to hand the issue back. While there is expense involved, any infrastructure I add to my code to avoid throwing the exception also adds expense.
Consider that for doubles, a division by zero will actually result in a value: double.Infinity, double.NegativeInfinity or double.NaN, depending upon whether the numerator is positive, negative or zero, respectively.
It may be that these values are already suitable for your case, if not you will probably want to validate the input, and act accordingly, before you perform the division.
If you are writing an API (such as on a library) and want to provide a contract that disallows a division by zero (say it exposes method that performs some kind of division) then you may want to throw this exception then. Typically though, I would reserve this type of exception as an indicator of a programmatic error.
If you are relying on a framework to do the work (.NET or otherwise), then you should let the framework throw the exception.
This will make it easier for consumers of your methods to handle exceptions that are thrown in a standard way.
In the case for dividing by zero, you are just re-implementing the same logic to throw an exception as in the framework.
Throwing an exception is an expensive thing to do from a resource point of view. You have already prevented an exception from occurring so why throw one? If you have to tell the user, use some messaging mechanism. If you need to know about it yourself, log it.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Do you prefer checked exception handling like in Java or unchecked exception handling like in C# and why?
I think checked exceptions are a failed experiment. The original goal of exception was to eliminate the need to validate every function call return, which was resulting in programs programs that are difficult to read, and probably inefficient as well, thus discouraging programmers from signaling and handling exceptions.
While great on paper, in practice the checked exceptions reintroduced the very same problem exception were supposed to eliminate in the first place. They add a tightly coupling between the layers of application. They make it impossible for libraries to change their implementation in subsequent versions. The link posted by crausher goes into details and explain the problems much better than I ever could.
Meh.
Checked exceptions are a great thing when used properly, but more often than not they lead to stuff like:
doSomething();
try
{
somethingThrowsCheckedException();
}
catch(ThatCheckedException)
{ }
doSomethingElse();
And, frankly, that's just wrong. You should let exceptions you don't handle bubble up.
Checked exceptions used properly can be good. But very frequently, the result of doing checked exceptions properly is method signatures like this:
public void itMightThrow() throws Exception1, Exception2, Exception3, Exception4, // ...
Exception12, Exception13, /* ... */ Exception4499379874
{
// body
}
Am I exaggerating? Only slightly.
Edit:
That said, one thing I prefer about C# over Java when it comes to exception handling has nothing to do with checked exceptions (I can get that if I go with Spec# anyway). No, what I like is that the stack trace in C# is populated when you throw an exception, rather than when you instantiate one as it is in Java.
Edit 2: This is for the commenters #Yishai, #Eddie, #Bill K:
First, you should check out this thread for information on how to get a stack trace without instantiating an exception. Keep in mind that walking the stack is a heavy process and should not be done on a regular basis.
Second, the reason I like C#'s exception stack trace being populated at throwal rather than at instantiation is that you can do things like this:
private MyException NewException(string message)
{
MyException e = new MyException(message);
Logger.LogException(message, e);
return e;
}
// and elsewhere...
if(mustThrow)
{
throw NewException("WHOOOOPSIEE!");
}
That's a trick you can't do in Java without having the NewException method included in the stack trace.
I prefer checked exceptions for things that can go wrong that you cannot predict ahead of time. For example, IOException, or SQLException. It tells the programmer that they have to account for something unpredictable going wrong, they cannot write robust code that will not throw an exception, no matter how much they try.
Too many times programmers view a checked exception as a language thing to handle. It isn't (or won't be in a well designed API) - it is an indication that there is unpredictable behavior inherent in the operation, and you should rely on a deterministic result of the operation always working the same given the same inputs.
That being said, in practice checked exceptions suffered from two things:
Not all applications written in Java need that robustness. A compiler-level flag to turn off checked exceptions would be nice - although that could lead to APIs abusing checked exceptions when their developers work with the flag set to turn them off. After thinking about a better comprimise here, my current thinking is that a compiler warning is the best ballance here. If checked exceptions were compiler warnings, including a compiler warning if one was ignored several layers down (so the fact that one was ignored would be compiled into the class), so that the caller would at least know to catch Exception even if he couldn't know which one, then those who don't care would ignore the compiler warning, and those who do would not, without anyone being forced to write error handling code they don't care about to get their code to compile.
Exception chaining took much too long (version 1.4) to introduce. The lack of exception chaining caused a lot of bad habits to develop early, instead of everyone just doing:
throw new RuntimeException(e);
when they didn't know what to do.
Also, a checked exception is another API design element to potentially get wrong, and the users of the API have to suffer with the design flaw.
EDIT: Another answer points to two issues that motivated the C# design decision of no checked exceptions. To my mind, both of those arguments are very bad, so I thought they were worth addressing/counter balancing.
Versioning. The argument is that if you change your API implementation and want to add additional checked exceptions, then you break existing client code.
Scallability. Before you know it you have a method that throws 15 checked exceptions.
I think both versions suffer from the unaddressed point that when those remarks were made it was already accepted that the proper way to deal with a checked exception moving up to the next level would be by wrapping a different checked exception appropriate to the abstraction of your API. For example, if you have a storage API that could deal with IOException, SQLException, or XML related exceptions, a properly desgined API would hide those differences behind a general PersistanceException or something like that.
Besides that general design guidance, in the specific the arguments really lead to a lot of questions about the alternatives:
Versioning. So a developer developed against your database API, thinking that they caught and handled the relevant exceptions (say DatabaseException) and then you decide in the next version to add a NetworkException to capture network level communication issues with the database. Now you just broke all compatability with existing code, and the compiler won't even complain about it. Everyone gets to discover it in regression testing, if they are lucky.
Scalability. In the C# solution, if three API levels down there is a potential for access to a volatile resource, you are relying entirely on the API documentation, because the compiler won't tell you that.
That is a great design for web apps where dying and showing the user a nice error 500 page is about all anyone bothers doing (since transactions are handled by the container anyway). But not all applications are built with such requirements in mind.
The argument ends up boiling down (to me anyway): Don't worry about exceptions, anything can go wrong and just build a catch-all.
OK. That is the core difference between a checked and unchecked exception approach. The checked exception alerts the programmer to volatile unpredictable calls. The unchecked exception approach just assumes that all error conditions are of the same class, they just have different names, and they are made unchecked so that no one goes around catching them.
Now the arguments do have merit at the CLR level. I agree that all checked exceptions should be at the compiler level, not the runtime level.
I have never used Java, but since I read
Why doesn't C# have exception specifications?
Does Java need Checked Exceptions?
The Trouble with Checked Exceptions
I am quite sure I don't like checked exceptions (in the current implementation).
The two main points mentioned are the following.
Versionability
Anders Hejlsberg: Let's start with versioning, because the issues are pretty easy to see there. Let's say I create a method foo that declares it throws exceptions A, B, and C. In version two of foo, I want to add a bunch of features, and now foo might throw exception D. It is a breaking change for me to add D to the throws clause of that method, because existing caller of that method will almost certainly not handle that exception.
Adding a new exception to a throws clause in a new version breaks client code. It's like adding a method to an interface. After you publish an interface, it is for all practical purposes immutable, because any implementation of it might have the methods that you want to add in the next version. So you've got to create a new interface instead. Similarly with exceptions, you would either have to create a whole new method called foo2 that throws more exceptions, or you would have to catch exception D in the new foo, and transform the D into an A, B, or C.
Scalability
Anders Hejlsberg: The scalability issue is somewhat related to the versionability issue. In the small, checked exceptions are very enticing. With a little example, you can show that you've actually checked that you caught the FileNotFoundException, and isn't that great? Well, that's fine when you're just calling one API. The trouble begins when you start building big systems where you're talking to four or five different subsystems. Each subsystem throws four to ten exceptions. Now, each time you walk up the ladder of aggregation, you have this exponential hierarchy below you of exceptions you have to deal with. You end up having to declare 40 exceptions that you might throw. And once you aggregate that with another subsystem you've got 80 exceptions in your throws clause. It just balloons out of control.
In the large, checked exceptions become such an irritation that people completely circumvent the feature. They either say, "throws Exception," everywhere; or—and I can't tell you how many times I've seen this—they say, "try, da da da da da, catch curly curly." They think, "Oh I'll come back and deal with these empty catch clauses later," and then of course they never do. In those situations, checked exceptions have actually degraded the quality of the system in the large.
OK, I wasn't going to reply, but this is taking too long to get closed and got many answers on one side of the fence, so I feel the need to weigh in on the other side.
I support checked exceptions -- when properly used -- and believe that they are a Good Thing. I've heard all of the arguments above many times, and there is some merit in some of the arguments against checked exceptions. But on net, I think they are positive. Having programmed in C# and Java, both, I find C# programs are more difficult to make stable against Exceptions. The great thing about checked exceptions is that the JavaDoc is guaranteed to tell you that the Exceptions can be thrown from that method. With C#, you rely on the coder to remember to tell you what exceptions may be thrown from any given method, and also what exceptions may be thrown from any method called by that method, and so on.
If you want to create 5-9's reliable code, you need to know what exceptions can be thrown from code that you call, so you can reason about what can be recovered from and what must cause you to abandon what you are doing. If C#, you can do this, but it involves a lot of trial and error until you have seen all of the possible exceptions that can be thrown. Or you just catch Exception and do your best.
There are pros and cons to both approaches, that of Java and C#. Reasoned arguments can be made in favor of both, and against both. Again, on net, I prefer the approach chosen by Java, but were I to re-write Java today, I would change the APIs to change some checked exceptions into runtime exceptions. The Java API is not consistent in its use of checked exceptions. And as someone else said, it took far too long for Exception chaining to appear as a standard API feature and a part of the JVM.
However, the charges that are lain at the feet of checked exceptions too often fall into the category of, "lazy programmers misuse this language feature." That's true. But that's true of many languages and their features. The "lazy programmer" argument is a weak one.
Let's address the main complaints that don't fall into the "lazy programmer" bucket:
Versionability - yes, throwing a new Exception in a new version of your code will break compilation for clients who blindly drop in your new JAR file. IMO, this is a good thing (as long as you have a good reason for throwing an additional checked exception), because the clients of your library have to reason about what they need to do with this behavior change. If everything is unchecked, then your clients don't necessarily have any clue (until an Exception occurs) that your behavior has changed. If you are changing the behavior of your code, then it's reasonable for your clients to have to know about this. Have you ever updated to a new version of a 3rd party library only to find its behavior has invisibly changed and now your program is broken? If you make a breaking behavior change in your library, you should break automatic compatibility with clients using earlier versions of your library.
Scalability - If you handle checked exceptions properly by translating them to a specific checked (or unchecked) exception appropriate to your layer of the API, this becomes a non-issue. That is, if you code properly, this problem disappears. And doing so, you properly hide your implementation details, which your callers shouldn't care about anyway.
Too often, this is simply a religious issue with people, and that's why I get (unnecessarily, I know) irritated. If you have a religious aversion to checked exceptions, that's OK. If you have a reasoned argument against checked exceptions, that's OK. I've seen good reasoned arguments (that I mostly don't agree with, but still...). But mostly I see bad arguments against checked exceptions, including arguments which were fair and reasonable when talking about Java 1.0, but which are no longer applicable given modern releases of Java.
In practice it is better to use checked exception handling as it allows for more detailed information when your app begins flooding error logs at 2AM and you get a call to do some debugging...
In my opinion there exist cases where checked exceptions are appropriate. There are probably features that could be done differently in Java to better support them. It isn't without difficulties (for instance, in some situations you might want an exception checked, in others not). Java does, of course, support unchecked exception types as well.
The sort of exceptions that are suitable to be checked should generally be documented. The best place to document is in the code. The populist approach is just to botch it and only consider the happy case.
Checked exceptions are great as long as they are recoverable or not due to programming errors like an invalid index acces to a ResultSet. Otherwise they tend to pollute code layers and APIs by forcing the coder to declare things like IOException in many method signatures and giving nothing really useful to the client code.
I think in most cases checked exception are a waste of time. They entrap to things like the antipattern mentioned by randolpho or extensive creation of custom exceptions to decouple your implementation from used libraries.
Beeing rid of this 'feature' lets you focus on what you want to do.
The only thing I'dd like the compiler to check for me is whether a function throws exceptions or not. What specific exceptions that can be thrown doesn't matter. The thing is that in my experience, there are a lot functions that don't throw anything, and it would be nice if this was documented in the function specification. For these functions you don't have to worry about exception handling.
Java has compiler checked exceptions. When I made transition to C++, I learned it doesn't feature checked exceptions. At first, I kept using exception handling, because it's a great feature. However, after a while I abandoned it, because I got into a situation every function might throw an exception. As only a small percentage of the functions I write can throw exceptions (say some 25% at the most), I found the overhead of doing exception handling for functions that cannot throw anything unacceptable.
Because of this, I am really surprised that there are a lot of developers who prefer unchecked exceptions. Therefore, I am curious to know how they handle this problem. How do you avoid the overhead of doing unnecessary exception handling in case the language doesn't support checked exceptions?
Remark: My question equally applies to C++ and C#, and probably to all other languages that don't feature compiler checked exception handling.
Simple. You don't do exception handling in "every function that might throw" - in C++, just about every function might do so. Instead, you do it at certain key points in your application, where you can produce a sensible, application-specific diagnostic and take sensible, application-specific corrective action, although use of the RAII idiom means (as avakar points out in his answer) that there is often little corrective action to be taken.
When I first started using C# I was scared by this too. Then I found that actually, it doesn't matter very often. I very rarely find that I can catch an exception and so something useful with it anyway... almost all my exceptions bubble up to somewhere near the top of the stack anyway, where they're handled by aborting the request or whatever.
Now when I'm writing Java, I find checked exceptions intensely frustrating a lot of the time. I think there's value in there somewhere, but it introduces as many problems as it solves.
Basically, I think we haven't really got the whole error handling side of things "right" yet, but on balance I prefer the C# approach to the Java approach.
In addition to what Neil said, you should note that there is no need for try/finally (or in context of C++ try/catch/throw), because object destructors are called even if an exception is thrown.
It is easily possible to have exception-safe code with very few try statements.
For C++ specifically, the overhead pretty much goes away if you design your classes well and use RAII.
Martin York has written a wonderful example of that in this answer.
The function can stll throw an exception, yes, but if it does, it won't need to do anything special to clean up. So you only need to actually catch the exception in one place -- the function that is able to handle it and recover from the error.