William said:
Tell, ya what. I'll recheck with the framework people on campus that told me
to avoid exceptions--you know, the people that wrote the code. My tests
clearly show that throwing an exception is very expensive in the framework
but I could be wrong. Let's ask another expert...
Oh dear. Name dropping is so... gauche. I'm impressed when people make
good arguments, not when they pull rank.
First, let me say that I agree with you in a limited way: some kinds of
errors should be handled via return messages or return codes, others
via exceptions. One example of the former would be bad user input: it
is expected and normal that users type garbage into applications, so
throwing an exception when the user does something "wrong" is overkill.
In my apps I return an error message string from the validation
routine, and then display that string to the user via an ErrorProvider
or a MessageBox. Score one for error returns.
However, the OP is talking about a data layer. Data layers often (but
not always) run off across networks and fetch volumes of information
from SQL databases. Compared to all of that, the cost of throwing an
exception from the data layer code is trifling. The point is, it's "too
expensive" compared to what? In what context? In the context of a
remote DB call, an exception doesn't even rate.
If you want to take a cue from somewhere, take a look at Microsoft's
own code: what does ADO.NET do when you do something that violates a
unique key constraint? It throws an exception. In fact, ADO.NET returns
error codes in very few cases. Mostly it throws exceptions, and that's
because compared to the cost of most ADO.NET operations, putting
together an exception and handling it isn't really all that costly.
The only place I've seen in which MS wrote code that throws exceptions
and then later backed off was the case of the Parse routines. In .NET
1.1 the only (reasonable) way to detect invalid input in some cases was
to do a .Parse() from the appropriate target type and then catch the
resulting FormatException. .NET 2.0 introduced TryParse() for types
that didn't have it before, simply because _in that case_ the cost of
an exception was too high _compared to the cost of the parse_.
Yes, one should not use exceptions willynilly. However, one must
consider the cost of throwing an exception with the cost of the
operation that failed. The more expensive the operation, in real and
CPU time, the less one should worry about the additional cost of
exceptions.