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.
精彩评论