473,699 Members | 2,433 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Exceptions as return values

I have had a lively discussion with some coworkers and decided to get
some general feedback on an issue that I could find very little
guidance on. Why is it considered bad practice to define a public
member with a return type that is derived from System.Exceptio n? I
understand the importance of having clean, concise code that follows
widely-accepted patterns and practices, but in this case, I find it
hard to blindly follow a standard when a better, more elegant solution
presents itself so readily.

I was writing a generic function to validate data that is going to be
used to represent key values for my business objects. It looked like
this:

public static ValidationExcep tion ValidateKeyArra y(System.Type
targetType, object[] keys);

ValidationExcep tion is derived from ApplicationExce ption, which, in
turn, derives from the base Exception class. The reason I chose to
write this in this way was to meet three requirements for this method:
a) Validation in itself should not throw an exception unless it cannot
figure out how to validate for some reason.
b) The code calling this method should be able to determine why
validation failed so it can either respond appropriately or throw an
exception if it can't recover
c) Figuring out why validation failed is not a separate logical process
from performing the validation itself, so it makes sense to have a
single function call to do both.

With the function written in this way (returning an object of type
ValidationExcep tion) I can:
1) Throw an exception if validation is impossible due to bad input, but
not have to throw an exception if the data is in the correct format but
is invalid
2) Return a descriptive error message in the ValidationExcep tion object
3) Return multiple error messages, if necessary (embedded in the
ValidationExcep tion object or attached to inner exceptions)
4) Avoid breaking normal program flow when validating, since failed
validation is not an error condition
5) Provide a throwable object to the caller so that critical validation
can be performed in two lines (ValidationExce ption x =
ValidateKeyArra y(type, array); if (x != null) throw x;)

As I understand them, the major alternatives are:

1) Returning a bool. This does not meet requirements (b) and (c).

2) Exposing validation information on the object, like the ASP.NET Page
object does. This would require a Validate method and an IsValid
property, and perhaps some sort of list to provide validation error
messages. This is considerably more code than the one I implemented,
and does not meet requirement (c). Also, validation exceptions would
not be standardized in any way, since I would be relying on the calling
code to throw an exception if it needs to.

3) Always throwing exceptions from the ValidateKeyArra y method, and
relying on the caller to use a try...catch block to manage it. If you
know that the input could be bad, shouldn't you avoid throwing an
exception at all?

4) Returning some sort of non-Exception-derived class to expose the
results of validation. The only real disadvantage here is that it
requires some extra code to extract the message from this object and
then put it into an Exception if you need to throw it.

I am looking forward to hearing your thoughts.

Daniel

Jan 9 '06 #1
14 3473
As I read your post, I went through a series of thoughts on the topic.
Initially, I thought you were nuts and you should either bubble up the
exception or catch it and handle it. However, it seems like you put a lot
of thought into the reasoning behind it and it's possible I could be
convinced if I read it again - not sure. I think the biggest problem is
just that the initial reaction is that it's counterintuitiv e to some.

Is there a better way to do it? I'm going to let someone else tackle that,
it would take a lot of thought and I'm on a pretty tight deadline for the
next couple weeks.

Craig

<dc*****@cmcdat aworks.com> wrote in message
news:11******** **************@ o13g2000cwo.goo glegroups.com.. .
I have had a lively discussion with some coworkers and decided to get
some general feedback on an issue that I could find very little
guidance on. Why is it considered bad practice to define a public
member with a return type that is derived from System.Exceptio n? I
understand the importance of having clean, concise code that follows
widely-accepted patterns and practices, but in this case, I find it
hard to blindly follow a standard when a better, more elegant solution
presents itself so readily.

I was writing a generic function to validate data that is going to be
used to represent key values for my business objects. It looked like
this:

public static ValidationExcep tion ValidateKeyArra y(System.Type
targetType, object[] keys);

ValidationExcep tion is derived from ApplicationExce ption, which, in
turn, derives from the base Exception class. The reason I chose to
write this in this way was to meet three requirements for this method:
a) Validation in itself should not throw an exception unless it cannot
figure out how to validate for some reason.
b) The code calling this method should be able to determine why
validation failed so it can either respond appropriately or throw an
exception if it can't recover
c) Figuring out why validation failed is not a separate logical process
from performing the validation itself, so it makes sense to have a
single function call to do both.

With the function written in this way (returning an object of type
ValidationExcep tion) I can:
1) Throw an exception if validation is impossible due to bad input, but
not have to throw an exception if the data is in the correct format but
is invalid
2) Return a descriptive error message in the ValidationExcep tion object
3) Return multiple error messages, if necessary (embedded in the
ValidationExcep tion object or attached to inner exceptions)
4) Avoid breaking normal program flow when validating, since failed
validation is not an error condition
5) Provide a throwable object to the caller so that critical validation
can be performed in two lines (ValidationExce ption x =
ValidateKeyArra y(type, array); if (x != null) throw x;)

As I understand them, the major alternatives are:

1) Returning a bool. This does not meet requirements (b) and (c).

2) Exposing validation information on the object, like the ASP.NET Page
object does. This would require a Validate method and an IsValid
property, and perhaps some sort of list to provide validation error
messages. This is considerably more code than the one I implemented,
and does not meet requirement (c). Also, validation exceptions would
not be standardized in any way, since I would be relying on the calling
code to throw an exception if it needs to.

3) Always throwing exceptions from the ValidateKeyArra y method, and
relying on the caller to use a try...catch block to manage it. If you
know that the input could be bad, shouldn't you avoid throwing an
exception at all?

4) Returning some sort of non-Exception-derived class to expose the
results of validation. The only real disadvantage here is that it
requires some extra code to extract the message from this object and
then put it into an Exception if you need to throw it.

I am looking forward to hearing your thoughts.

Daniel

Jan 9 '06 #2
Daniel,

I think the main issue here is one of logical constructs. A validation
method would normally return true or false - that's accepted practice. If
you feel your validation method needs to return more information -- such as
why validation failed, etc., I'd consider creating a ValidationResul t class
containing this additional information, and return an instance of that rather
than an exception.
Exceptions are expensive, rack up a lot of CPU cycles, and they're really
for one purpose - something Exceptional.

Validation failing is a normal and expected business logic result, and
should not result in an exception.
Hope that helps,
Peter
--
Co-founder, Eggheadcafe.com developer portal:
http://www.eggheadcafe.com
UnBlog:
http://petesbloggerama.blogspot.com


"dc*****@cmcdat aworks.com" wrote:
I have had a lively discussion with some coworkers and decided to get
some general feedback on an issue that I could find very little
guidance on. Why is it considered bad practice to define a public
member with a return type that is derived from System.Exceptio n? I
understand the importance of having clean, concise code that follows
widely-accepted patterns and practices, but in this case, I find it
hard to blindly follow a standard when a better, more elegant solution
presents itself so readily.

I was writing a generic function to validate data that is going to be
used to represent key values for my business objects. It looked like
this:

public static ValidationExcep tion ValidateKeyArra y(System.Type
targetType, object[] keys);

ValidationExcep tion is derived from ApplicationExce ption, which, in
turn, derives from the base Exception class. The reason I chose to
write this in this way was to meet three requirements for this method:
a) Validation in itself should not throw an exception unless it cannot
figure out how to validate for some reason.
b) The code calling this method should be able to determine why
validation failed so it can either respond appropriately or throw an
exception if it can't recover
c) Figuring out why validation failed is not a separate logical process
from performing the validation itself, so it makes sense to have a
single function call to do both.

With the function written in this way (returning an object of type
ValidationExcep tion) I can:
1) Throw an exception if validation is impossible due to bad input, but
not have to throw an exception if the data is in the correct format but
is invalid
2) Return a descriptive error message in the ValidationExcep tion object
3) Return multiple error messages, if necessary (embedded in the
ValidationExcep tion object or attached to inner exceptions)
4) Avoid breaking normal program flow when validating, since failed
validation is not an error condition
5) Provide a throwable object to the caller so that critical validation
can be performed in two lines (ValidationExce ption x =
ValidateKeyArra y(type, array); if (x != null) throw x;)

As I understand them, the major alternatives are:

1) Returning a bool. This does not meet requirements (b) and (c).

2) Exposing validation information on the object, like the ASP.NET Page
object does. This would require a Validate method and an IsValid
property, and perhaps some sort of list to provide validation error
messages. This is considerably more code than the one I implemented,
and does not meet requirement (c). Also, validation exceptions would
not be standardized in any way, since I would be relying on the calling
code to throw an exception if it needs to.

3) Always throwing exceptions from the ValidateKeyArra y method, and
relying on the caller to use a try...catch block to manage it. If you
know that the input could be bad, shouldn't you avoid throwing an
exception at all?

4) Returning some sort of non-Exception-derived class to expose the
results of validation. The only real disadvantage here is that it
requires some extra code to extract the message from this object and
then put it into an Exception if you need to throw it.

I am looking forward to hearing your thoughts.

Daniel

Jan 10 '06 #3
Daniel,

I have mixed feelings about this. Also, I think that there needs to be
a correction.

Peter wasn't too clear when he said that exceptions are expensive.
Exceptions are expensive if they are thrown. Creating them, on the other
hand, isn't that expensive. When an exception is created, the stack trace
isn't populated (which is the one thing I can think of which would be
expensive in constructing an exception, but the stack trace is populated
when it is thrown, not when it is created, so it is a non issue).

Now, there is a lot of ingrained thinking about using exceptions like
other objects. We are pretty much given the impression that they are only
to be thrown.

However, they seem to suit your need, and because you are reusing
existing code to suit your needs, it works out well.

I agree with these reasons for using it, and on the surface, it is a
good idea.

However, there is one thing that has been neglected in this discussion
up to this point. That is the fact that whatever you return can be thrown
by any section of code. This is a BIG issue, IMO, as you are giving other
code to really throw something which is specific to your problem domain.
That's just not cool. Granted, in C++, you can throw anything (it doesn't
have to be limited to an object derived from exception), but in most other
..NET languages, you have to derive from exception.

For that reason alone, I think that it is a good idea to create your own
class which will expose the properties you need, which indicates the error
states/information for failed buisiness logic (but not critical errors).

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m
<dc*****@cmcdat aworks.com> wrote in message
news:11******** **************@ o13g2000cwo.goo glegroups.com.. .
I have had a lively discussion with some coworkers and decided to get
some general feedback on an issue that I could find very little
guidance on. Why is it considered bad practice to define a public
member with a return type that is derived from System.Exceptio n? I
understand the importance of having clean, concise code that follows
widely-accepted patterns and practices, but in this case, I find it
hard to blindly follow a standard when a better, more elegant solution
presents itself so readily.

I was writing a generic function to validate data that is going to be
used to represent key values for my business objects. It looked like
this:

public static ValidationExcep tion ValidateKeyArra y(System.Type
targetType, object[] keys);

ValidationExcep tion is derived from ApplicationExce ption, which, in
turn, derives from the base Exception class. The reason I chose to
write this in this way was to meet three requirements for this method:
a) Validation in itself should not throw an exception unless it cannot
figure out how to validate for some reason.
b) The code calling this method should be able to determine why
validation failed so it can either respond appropriately or throw an
exception if it can't recover
c) Figuring out why validation failed is not a separate logical process
from performing the validation itself, so it makes sense to have a
single function call to do both.

With the function written in this way (returning an object of type
ValidationExcep tion) I can:
1) Throw an exception if validation is impossible due to bad input, but
not have to throw an exception if the data is in the correct format but
is invalid
2) Return a descriptive error message in the ValidationExcep tion object
3) Return multiple error messages, if necessary (embedded in the
ValidationExcep tion object or attached to inner exceptions)
4) Avoid breaking normal program flow when validating, since failed
validation is not an error condition
5) Provide a throwable object to the caller so that critical validation
can be performed in two lines (ValidationExce ption x =
ValidateKeyArra y(type, array); if (x != null) throw x;)

As I understand them, the major alternatives are:

1) Returning a bool. This does not meet requirements (b) and (c).

2) Exposing validation information on the object, like the ASP.NET Page
object does. This would require a Validate method and an IsValid
property, and perhaps some sort of list to provide validation error
messages. This is considerably more code than the one I implemented,
and does not meet requirement (c). Also, validation exceptions would
not be standardized in any way, since I would be relying on the calling
code to throw an exception if it needs to.

3) Always throwing exceptions from the ValidateKeyArra y method, and
relying on the caller to use a try...catch block to manage it. If you
know that the input could be bad, shouldn't you avoid throwing an
exception at all?

4) Returning some sort of non-Exception-derived class to expose the
results of validation. The only real disadvantage here is that it
requires some extra code to extract the message from this object and
then put it into an Exception if you need to throw it.

I am looking forward to hearing your thoughts.

Daniel

Jan 10 '06 #4
One thing you need to realize, that if you're validating information
(such as user input), then effectively, you're making sure that there
isn't bad data. Exceptions are for exceptional circumstances. Bad
data isn't an exceptional circumstance, it happens all the time!

There tends to be great deal of difference between definitions of an
"Exception" . Exceptions are extremely expensive to throw and catch,
therefore, if you can avoid them or come up with alternatives, then by
all means, do it! To prove to a coworker on how expensive it is to
throw and catch exceptions, I set up a simple example. Take the
DivideByZeroExc eption for example. This is thrown whenever you attempt
to divide an integer by zero. The reason this is thrown, is that there
is absolutely no way whatsoever that that particular operation can
continue, because of the bounds of mathematics. So, take the following
samples on how to address this problem.

public int DivideBy(int divisor)
{
try
{
return 1 / divisor;
}
catch (Exception ex)
{
return 0;
}
}

This simply will attempt to divide 1 by the number entered into the
method. If it fails, it just returns 0. Now, take this example:

public int DivideBy(int divisor)
{
if (divisor != 0)
return 1 / divisor;
else
return 0;
}

This is slightly different, but with the same results. Identical? Not
even close! In my test to a coworker, I called each method one million
times, to see how long it would take. The method which checks for zero
first took only a few milliseconds to race through the method a million
times. The version which used brute force, and wrapped it in a
try/catch block took over 5 minutes!!

Here are a few guidelines on when and when not to use exceptions.

1) When a method absolutely, positively cannot complete what it is
meant to do, and has exhausted every last possible work around, and
simply cannot recover from something, then an exception should be
thrown. Examples of this would be necessary resources are not present,
such as a database, network connection, web service, file system,
security credentials, etc. Example: The File.Open() method cannot open
a file because it does not exist. Its purpose is to open a file, and
stream the contents back to you. If the file does not exist, it cannot
perform its intended action. It cannot complete its purpose in life.
It doesn't create a new file, because that's not its purpose. It
doesn't send another file, because that's not its purpose either.
However, there IS a work around! File.Exists() is provided to avoid
that exception altogether! There IS a work around without the need for
a try/catch block around the File.Open() method.

2) Do NOT use an exception to communicate between classes/layers/tiers.
Unless you're unit testing, there is no such thing as an "Expected
Exception". Business logic should not contain reasoning saying, "This
method _might_ throw an exception 50% of the time for various reasons,
so its important to have it inside of a try/catch block." This goes
back to the expensive nature of exceptions. Returning an exception as
you propose is interesting, but doesn't hold true to the concept of
validation. Validating that a correct username and password is passed
by the user has a very high likelyhood that they would come back wrong.
An exception definitely shouldn't be "bubbled up" from any of the
tiers for an event like this. Its expected behavior, and should be
handled through events, method return values, or some other mechanism.
However, "The database server is currently on fire, and the network
cables have melted" is certainly an exception. You NEVER anticipated
this to ever happen, and honestly, short of automatically calling the
fire department, this is not recoverable.

Proper coding techniques can greatly reduce the amount of exceptions
that we have to deal with on a day-to-day basis. I'm sure we've all
gotten NullReferenceEx ceptions at least 50 times a week:

string a = myObject.ToStri ng(); // throws an exception is myObject is
null.

The answer isn't to wrap it with a try/catch block:

try
{
string a = myObject.ToStri ng();
}
catch {}

This is just expensive, especially since there is a much better work
around:

if (myObject != null)
string a = myObject.ToStri ng();

I'm in no way, shape, or form advocating against exceptions, or
try/catch blocks, however, I've seen them abused, misused, and overused
almost daily. They have their purpose in modern day programming, and
their proper use will make us all better programmers.

Hope this helps!

Brant Estes
Senior Consultant
Magenic Technologies

Jan 10 '06 #5
I agree with all your points - especially about ingrained attitudes.
Anytime thinking is replaced with rote behavior it leads to unfortunate
results.

I'd add one thing to your points. The OP stated he derived his exception
from the ApplicationExce ption class; I feel this is a rather useless
exception type; it does nothing to communicate the cause of an exception,
and it adds depth to the exception hierarchy but adds little of value. I
prefer to derive directly from Exception, or perhaps use a more descriptive
exception type, such as ArgumentExcepti on, rather then ApplicationExce ption
or a custom exception. I prefer to avoid custom exception types unless I
have a great deal of control over their usage - if the exception were to be
propagated across a appdomain, process, or machine boundary, then unless the
assembly that contains the definition of the custom exception is present and
of the correct version, the exception object cannot be deserialized on the
client side of the boundary, resulting in a different, and very likely,
misleading exception. To avoid this I prefer to use standard exception types
defined in the BCL.

I like exposing the exception as a property of the validation class; as the
OP stated, this provides the user of the class the option of how to deal
with the exception. It also provides the option for the client to throw the
exception on a different thread if necessary. For example, the client can
launch a worker thread to process a number items to be validated, and any
exceptions can be rethrown on the original thread when the worker thread is
done.

regards,
Dave

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c om> wrote in
message news:eC******** ******@TK2MSFTN GP11.phx.gbl...
Daniel,

I have mixed feelings about this. Also, I think that there needs to be
a correction.

Peter wasn't too clear when he said that exceptions are expensive.
Exceptions are expensive if they are thrown. Creating them, on the other
hand, isn't that expensive. When an exception is created, the stack trace
isn't populated (which is the one thing I can think of which would be
expensive in constructing an exception, but the stack trace is populated
when it is thrown, not when it is created, so it is a non issue).

Now, there is a lot of ingrained thinking about using exceptions like
other objects. We are pretty much given the impression that they are only
to be thrown.

However, they seem to suit your need, and because you are reusing
existing code to suit your needs, it works out well.

I agree with these reasons for using it, and on the surface, it is a
good idea.

However, there is one thing that has been neglected in this discussion
up to this point. That is the fact that whatever you return can be thrown
by any section of code. This is a BIG issue, IMO, as you are giving other
code to really throw something which is specific to your problem domain.
That's just not cool. Granted, in C++, you can throw anything (it doesn't
have to be limited to an object derived from exception), but in most other
.NET languages, you have to derive from exception.

For that reason alone, I think that it is a good idea to create your
own class which will expose the properties you need, which indicates the
error states/information for failed buisiness logic (but not critical
errors).

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m
<dc*****@cmcdat aworks.com> wrote in message
news:11******** **************@ o13g2000cwo.goo glegroups.com.. .
I have had a lively discussion with some coworkers and decided to get
some general feedback on an issue that I could find very little
guidance on. Why is it considered bad practice to define a public
member with a return type that is derived from System.Exceptio n? I
understand the importance of having clean, concise code that follows
widely-accepted patterns and practices, but in this case, I find it
hard to blindly follow a standard when a better, more elegant solution
presents itself so readily.

I was writing a generic function to validate data that is going to be
used to represent key values for my business objects. It looked like
this:

public static ValidationExcep tion ValidateKeyArra y(System.Type
targetType, object[] keys);

ValidationExcep tion is derived from ApplicationExce ption, which, in
turn, derives from the base Exception class. The reason I chose to
write this in this way was to meet three requirements for this method:
a) Validation in itself should not throw an exception unless it cannot
figure out how to validate for some reason.
b) The code calling this method should be able to determine why
validation failed so it can either respond appropriately or throw an
exception if it can't recover
c) Figuring out why validation failed is not a separate logical process
from performing the validation itself, so it makes sense to have a
single function call to do both.

With the function written in this way (returning an object of type
ValidationExcep tion) I can:
1) Throw an exception if validation is impossible due to bad input, but
not have to throw an exception if the data is in the correct format but
is invalid
2) Return a descriptive error message in the ValidationExcep tion object
3) Return multiple error messages, if necessary (embedded in the
ValidationExcep tion object or attached to inner exceptions)
4) Avoid breaking normal program flow when validating, since failed
validation is not an error condition
5) Provide a throwable object to the caller so that critical validation
can be performed in two lines (ValidationExce ption x =
ValidateKeyArra y(type, array); if (x != null) throw x;)

As I understand them, the major alternatives are:

1) Returning a bool. This does not meet requirements (b) and (c).

2) Exposing validation information on the object, like the ASP.NET Page
object does. This would require a Validate method and an IsValid
property, and perhaps some sort of list to provide validation error
messages. This is considerably more code than the one I implemented,
and does not meet requirement (c). Also, validation exceptions would
not be standardized in any way, since I would be relying on the calling
code to throw an exception if it needs to.

3) Always throwing exceptions from the ValidateKeyArra y method, and
relying on the caller to use a try...catch block to manage it. If you
know that the input could be bad, shouldn't you avoid throwing an
exception at all?

4) Returning some sort of non-Exception-derived class to expose the
results of validation. The only real disadvantage here is that it
requires some extra code to extract the message from this object and
then put it into an Exception if you need to throw it.

I am looking forward to hearing your thoughts.

Daniel


Jan 10 '06 #6
Brant Estes <br****@magenic .com> wrote:
One thing you need to realize, that if you're validating information
(such as user input), then effectively, you're making sure that there
isn't bad data. Exceptions are for exceptional circumstances. Bad
data isn't an exceptional circumstance, it happens all the time!
Not "all the time" I'd say. Reasonably frequently - but exceptions
aren't actually *that* expensive IMO. I think it's very rare that
choosing to use an exception when it's not *obviously* wrong would
actually add a significant overhead.

Unless you're *really* throwing exceptions in a pretty tight loop (like
in your example) they're unlikely to make much difference. Usually
exceptions bubble up several stack frames, which usually means they're
*not* going to be part of a tight loop (and shouldn't be).

Note that if you're validating user input, the time taken to throw an
exception is going to be *much* shorter than the time taken to accept
the input in the first place...
There tends to be great deal of difference between definitions of an
"Exception" . Exceptions are extremely expensive to throw and catch,
therefore, if you can avoid them or come up with alternatives, then by
all means, do it! To prove to a coworker on how expensive it is to
throw and catch exceptions, I set up a simple example. Take the
DivideByZeroExc eption for example. This is thrown whenever you attempt
to divide an integer by zero. The reason this is thrown, is that there
is absolutely no way whatsoever that that particular operation can
continue, because of the bounds of mathematics. So, take the following
samples on how to address this problem.

public int DivideBy(int divisor)
{
try
{
return 1 / divisor;
}
catch (Exception ex)
{
return 0;
}
}

This simply will attempt to divide 1 by the number entered into the
method. If it fails, it just returns 0. Now, take this example:

public int DivideBy(int divisor)
{
if (divisor != 0)
return 1 / divisor;
else
return 0;
}

This is slightly different, but with the same results. Identical? Not
even close! In my test to a coworker, I called each method one million
times, to see how long it would take. The method which checks for zero
first took only a few milliseconds to race through the method a million
times. The version which used brute force, and wrapped it in a
try/catch block took over 5 minutes!!
In a debugger, I suspect. What do you get if you run the following from
a command line? On my box, it took 15 seconds - I doubt that my laptop
is 20 times faster than your box! Throwing exceptions is *much* slower
in a debugger than not, which is something people often overlook.

using System;

class Test
{
static void Main()
{
DateTime start = DateTime.Now;
for (int i=0; i < 1000000; i++)
{
DivideBy(0);
}
Console.WriteLi ne (DateTime.Now-start);
}

public static int DivideBy(int divisor)
{
try
{
return 1 / divisor;
}
catch (Exception)
{
return 0;
}
}

}

<snip>
2) Do NOT use an exception to communicate between classes/layers/tiers.
Unless you're unit testing, there is no such thing as an "Expected
Exception". Business logic should not contain reasoning saying, "This
method _might_ throw an exception 50% of the time for various reasons,
so its important to have it inside of a try/catch block." This goes
back to the expensive nature of exceptions.
It shouldn't. The use of exceptions should be much more due to what
ends up being the most elegant code rather than performance unless the
exceptions are *shown* to cause a performance problem. Why bend a
design out of shape for the sake of something which may well not be a
significant overhead anyway?
I'm in no way, shape, or form advocating against exceptions, or
try/catch blocks, however, I've seen them abused, misused, and overused
almost daily. They have their purpose in modern day programming, and
their proper use will make us all better programmers.


Likewise I'm not advocating the use of exceptions everywhere. However,
I've seen return codes abused, misused and overused frequently, often
because people have an exaggerated view of how expensive exceptions
are. (The DivideByZeroExc eption thrown in your example is relatively
expensive, actually - if you change the code to just throw and catch an
exception, it takes half as long on my box.)

See http://www.pobox.com/~skeet/csharp/exceptions.html for more on my
views on this.

--
Jon Skeet - <sk***@pobox.co m>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jan 10 '06 #7
Jon wrote:

<snip>
In a debugger, I suspect. What do you get if you run the following from
a command line? On my box, it took 15 seconds - I doubt that my laptop
is 20 times faster than your box! Throwing exceptions is *much* slower
in a debugger than not, which is something people often overlook.


I've just tried this again with .NET 2.0, and it's more than twice as
slow, both at explicitly throwing and catching an exception and in the
division by zero situation. Maybe that's accounting for some of the
discrepancy?

Either way, I'd certainly say that if someone is throwing hundreds of
thousands of exceptions a minute, they're abusing exceptions - but that
doesn't rule it out nearly as much as many believe.

I think the OP's scheme of returning an exception is a good one - the
exception can be thrown where it's appropriate (eg if log files were
being processed, and those log files really shouldn't contain bad data)
and not where it's not appropriate.

Jon

Jan 10 '06 #8
Nick,
True of course on being expensive only when thrown and the bigger picture
concept of a return-value exception from a method being able to be thrown
outside the problem domain.

Also, let's think about working with other developers. Conceptually the idea
seems sound (as Jon pointed out) but what about other developers having to
work with this code - who've never seen anybody do something like this? ( I
haven't - although I've seen an exception being set as a property - not sure
what the intent was though).

Although Daniel should be complemented for his lateral thinking prowess, I'd
still vote for trying first to see if the same effective result could be
accomplished in a more "accepted", best-practices-methodology before
departing into these waters.
Peter
--
Co-founder, Eggheadcafe.com developer portal:
http://www.eggheadcafe.com
UnBlog:
http://petesbloggerama.blogspot.com


"Nicholas Paldino [.NET/C# MVP]" wrote:
Daniel,

I have mixed feelings about this. Also, I think that there needs to be
a correction.

Peter wasn't too clear when he said that exceptions are expensive.
Exceptions are expensive if they are thrown. Creating them, on the other
hand, isn't that expensive. When an exception is created, the stack trace
isn't populated (which is the one thing I can think of which would be
expensive in constructing an exception, but the stack trace is populated
when it is thrown, not when it is created, so it is a non issue).

Now, there is a lot of ingrained thinking about using exceptions like
other objects. We are pretty much given the impression that they are only
to be thrown.

However, they seem to suit your need, and because you are reusing
existing code to suit your needs, it works out well.

I agree with these reasons for using it, and on the surface, it is a
good idea.

However, there is one thing that has been neglected in this discussion
up to this point. That is the fact that whatever you return can be thrown
by any section of code. This is a BIG issue, IMO, as you are giving other
code to really throw something which is specific to your problem domain.
That's just not cool. Granted, in C++, you can throw anything (it doesn't
have to be limited to an object derived from exception), but in most other
..NET languages, you have to derive from exception.

For that reason alone, I think that it is a good idea to create your own
class which will expose the properties you need, which indicates the error
states/information for failed buisiness logic (but not critical errors).

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m
<dc*****@cmcdat aworks.com> wrote in message
news:11******** **************@ o13g2000cwo.goo glegroups.com.. .
I have had a lively discussion with some coworkers and decided to get
some general feedback on an issue that I could find very little
guidance on. Why is it considered bad practice to define a public
member with a return type that is derived from System.Exceptio n? I
understand the importance of having clean, concise code that follows
widely-accepted patterns and practices, but in this case, I find it
hard to blindly follow a standard when a better, more elegant solution
presents itself so readily.

I was writing a generic function to validate data that is going to be
used to represent key values for my business objects. It looked like
this:

public static ValidationExcep tion ValidateKeyArra y(System.Type
targetType, object[] keys);

ValidationExcep tion is derived from ApplicationExce ption, which, in
turn, derives from the base Exception class. The reason I chose to
write this in this way was to meet three requirements for this method:
a) Validation in itself should not throw an exception unless it cannot
figure out how to validate for some reason.
b) The code calling this method should be able to determine why
validation failed so it can either respond appropriately or throw an
exception if it can't recover
c) Figuring out why validation failed is not a separate logical process
from performing the validation itself, so it makes sense to have a
single function call to do both.

With the function written in this way (returning an object of type
ValidationExcep tion) I can:
1) Throw an exception if validation is impossible due to bad input, but
not have to throw an exception if the data is in the correct format but
is invalid
2) Return a descriptive error message in the ValidationExcep tion object
3) Return multiple error messages, if necessary (embedded in the
ValidationExcep tion object or attached to inner exceptions)
4) Avoid breaking normal program flow when validating, since failed
validation is not an error condition
5) Provide a throwable object to the caller so that critical validation
can be performed in two lines (ValidationExce ption x =
ValidateKeyArra y(type, array); if (x != null) throw x;)

As I understand them, the major alternatives are:

1) Returning a bool. This does not meet requirements (b) and (c).

2) Exposing validation information on the object, like the ASP.NET Page
object does. This would require a Validate method and an IsValid
property, and perhaps some sort of list to provide validation error
messages. This is considerably more code than the one I implemented,
and does not meet requirement (c). Also, validation exceptions would
not be standardized in any way, since I would be relying on the calling
code to throw an exception if it needs to.

3) Always throwing exceptions from the ValidateKeyArra y method, and
relying on the caller to use a try...catch block to manage it. If you
know that the input could be bad, shouldn't you avoid throwing an
exception at all?

4) Returning some sort of non-Exception-derived class to expose the
results of validation. The only real disadvantage here is that it
requires some extra code to extract the message from this object and
then put it into an Exception if you need to throw it.

I am looking forward to hearing your thoughts.

Daniel


Jan 10 '06 #9
You can think of the validation method as a sort of exception factory
and it's up to the calling code to determine whether or not there is an
actual error condition, based on its needs. That was my original
intent in structuring my code inthis way. Much like we create business
object managers to centralize access to data and it's up to the calling
code to use them to solve business problems, an exception in itself
describes a potential error state, and it has the useful feature of
being able to be thrown without being wrapped in another class.

I guess I see the problem domain of an exception as not necessarily
local to the method that instantiates it. But, as several people
pointed out, programmers just don't expect to see an exception until
it's being thrown, and I've been coding long enough to know that it's
worth making your intentions clear in the way you structure your code.
So the suggestion of a separate class exposing the validation
information makes lots of sense.

But the problem is that if I have three different methods that call
ValidateKeyArra y, they all would be separately responsible for turning
this ValidationResul t class into an exception. This would mean that
this new class would then be responsible for generating exceptions if I
want to keep it centralized. A RaiseException method on the
ValidationResul t would seem equally as weird as my original solution.
I think you implied at the end of your response that you would separate
handling for failed business logic and true error states, but I don't
know that the ValidationResul t class can know one from the other.
Maybe my original method's semantics are wrong?

Jan 10 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
2336
by: Gianni Mariani | last post by:
I'm involved in a new project and a new member on the team has voiced a strong opinion that we should utilize exceptions. The other members on the team indicate that they have either been burned with unmaintainable code (an so are now not using exceptions). My position is that "I can be convinced to use exceptions" and my experience was that it let to code that was (much) more difficult to debug. The team decided that we'd give...
10
1548
by: Jakob Bieling | last post by:
Hi, somehow the prejudice of exceptions being rather slow (compared to, ie. returning an error value and checking that) keeps sticking around .. at least around me. I guess this is also why I refrained from using them often. But are they 'slow' in general? I guess it also depends on how, when and where you use them. What I am looking for is a sort of guideline that explains where exceptions are approriate and where they are not. The...
15
426
by: Bernard | last post by:
Hi All, I am not sure if I should be asking this question on clc or clc++. Let me try on both. I hope that this is not too trivial for the brilliant minds over here. I know that OOP questions have been asked on clc before so it is probably OK. I am a newbie to C++. BS 3rd edition states: % The throw transfers control to a handler for exceptions .... %
10
1295
by: Razzie | last post by:
Hi all, The title of this post may sound a bit weird, but I was wondering about the following nonetheless. I have a class libray containing, say, 4 classes: A, B, C, D. Class A somehow has a reference to B, B has a reference to C, and C to D. If an exception happens in class D, I would like class A to get a notification of this (all execution on classes B to D should be terminated). I am wondering how to do this. The following seems...
8
2254
by: cat | last post by:
I had a long and heated discussion with other developers on my team on when it makes sense to throw an exception and when to use an alternate solution. The .NET documentation recommends that an exception should be thrown only in exceptional situations. It turned out that each of my colleagues had their own interpretation about what an "exceptional situation" may actually be. First of all, myself I’m against using exceptions extensively,...
4
1852
by: Steve | last post by:
I have read a couple articles online, read my Jesse Liberty book but I am still confused as to just what the best practices are for using exceptions. I keep changing how I'm working with them and it has now, after 15k lines of code resulted in a royal mess! It's my hope to ask some specific questions with scenario examples and that some of you might offer a little guidance or general suggestions. 1) string...
42
3014
by: Jon Harrop | last post by:
Why are exceptions in C++ ~6x slower than exceptions in OCaml? -- Dr Jon D Harrop, Flying Frog Consultancy Objective CAML for Scientists http://www.ffconsultancy.com/products/ocaml_for_scientists/index.html?usenet
6
2049
by: Liming | last post by:
Hi, In a typical 3 tier model (view layer, busines layer and data access layer) where do you handle your exceptions? do you let it buble up all the way to the .aspx pages or do you handle it in your business layer and/or data access layer? suppose in my data access layer, I provide try and catch, log the exception and re-throw it back to business layer, then in yoru business layer, what do you do? throw it back to the code behind or...
17
1739
by: Christoph Zwerschke | last post by:
I'm just reading PEP 3107 (function annotations) and wonder why exceptions are not mentioned there. I think it would be helpful if one could specify which exceptions can be raised by a function, similarly to how it is possible in C++ using the "throw" clause. The syntax would be something like this: def foo(a: expr, b: expr = 5) raises expr -expr: The expr in that "raises" clause should be a list of Exceptions.
0
8705
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8623
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
1
8941
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8897
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7785
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6549
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4390
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4637
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3071
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.