tags:

views:

1550

answers:

22

My question boils down to : “Why not use exception (or error- for that matter) handling for regular program flow? To avoid all standard-answers I could have googled on, I will provide an example you all can attack at will.

C# and Java (and too many others) have with plenty of types some of ‘overflow’ behaviour I don’t like at all. (type.MaxValue + type.SmallestValue == type.MinValue for example : int.MaxValue + 1 == int.MinValue). But, seen my vicious nature, I’ll add some insult to this injury and even expand this behaviour to, let’s say an Overridden DateTime type. (I know DateTime is sealed in .NET, but for the sake of this example, I’m using a pseudo language that is exactly like C#, except for the fact that DateTime isn’t sealed :-))

The overridden Add method :

        /// <summary>
        /// Increments this date with a timespan, but loops when
        /// the maximum value for datetime is exceeded.
        /// </summary>
        /// <param name="ts">The timespan to (try to) add</param>
        /// <returns>The Date, incremented with the given timespan. 
        /// If DateTime.MaxValue is exceeded, the sum wil 'overflow' and 
        /// continue from DateTime.MinValue. 
        /// </returns>
        public DateTime override Add(TimeSpan ts) 
        {
            try
            {                
                return base.Add(ts);
            }
            catch (ArgumentOutOfRangeException nb)
            {
                // calculate how much the MaxValue is exceeded
                // regular program flow
                TimeSpan saldo = ts - (base.MaxValue - this);
                return DateTime.MinValue.Add(saldo)                   
            }
            catch(Exception anyOther) 
            {
                // 'real' exception handling.
            }
        }

Of course an if could solve this just as easy, but the fact remains that I just fail to see why you couldn’t use exceptions (logically that is, I can see that when performance is an issue that in certain cases exceptions should be avoided). I think in many cases they are more clear than if-structures and don’t break any contract the method is making.

IMHO The “Never use them for regular program flow”-reaction everybody seems to have is not that well underbuild as the strength of that reaction can justify.

Or am I mistaken?

I've read other posts, dealing with all kind of special cases, but my point is : if you are 1. Clear and 2. Hounour the contract of your method,

there's nothing wrong with it. Shoot me.

+43  A: 

Exceptions are basically non-local goto statements with all the consequences of the latter. Using exceptions for flow control violates a principle of least astonishment, make programs hard to read (remember that programs are written for programmers first).

Moreover, this is not what compiler vendors expect. They expect exceptions to be thrown rarely, and they usually let the throw code be quite inefficient. Throwing exceptions is one of the most expensive operations in .NET.

However, some languages (notably Python) use exceptions as flow-control constucts. For example, iterators raise a StopIteration exception if there are no further items. Even standard language constructs (such as for) rely on this.

Anton Gogolev
Most clear answer I've ever had concerning this, I will explore it further when I have more time
Peter
hey, exceptions are not astonishing! And you kinda contradict yourself when you say "it's a bad idea" and then go on to say "but it's a good idea in python".
hasen j
I never said that it's a good idea in Python.
Anton Gogolev
I'm still not convinced at all : 1) Effiency was besides the question, lots of non bacht programs couldn't care less (eg user interface) 2) Astonishing : like I said it's just astonishing cause it isn't used, but the question remains : why not use id in the first place? But, since this is the answer
Peter
that was the clearest and certainly was interesting, I chose to accept it.
Peter
If I remember correctly the iterating for statement in Java (for (foo : bar)) relies on exceptions as well to abort. There was no guarantee that hasNext() will be called and iirc it won't.
Joey
+8  A: 

My rule of thumb is:

  • If you can do anything to recover from an error, catch exceptions
  • If the error is a very common one (eg. user tried to log in with the wrong password), use returnvalues
  • If you can't do anything to recover from an error, leave it uncatched (Or catch it in your main-catcher to do some semi-gracefull shutdown of the application)

The problem I see with exceptions is from a purely syntax point of view (I'm pretty sure the perfomance overhead is minimal). I don't like try-blocks all over the place.

Take this example:

try
{
   DoSomeMethod();  //Can throw Exception1
   DoSomeOtherMethod();  //Can throw Exception1 and Exception2
}
catch(Exception1)
{
   //Okay something messed up, but is it SomeMethod or SomeOtherMethod?
}

.. Another example could be when you need to assign something to a handle using a factory, and that factory could throw an exception:

Class1 myInstance;
try
{
   myInstance = Class1Factory.Build();
}
catch(SomeException)
{
   // Couldn't instantiate class, do something else..
}
myInstance.BestMethodEver();   // Will throw a compile-time error, saying that myInstance is uninitalized, which it potentially is.. :(

Soo, personally, I think you should keep exceptions for rare error-conditions (out of memory etc.) and use returnvalues (valueclasses, structs or enums) to do your error checking instead.

Hope I understood your question correct :)

cwap
re: Your second example - why not just put the call to BestMethodEver inside the try block, after Build? If Build() throws an exception, it will not be executed, and the compiler is happy.
Blorgbeard
Yup, that would probably be what you'll end up with, but consider a more complex example where the myInstance-type itself can throw exceptions.. And other isntances in the method scope can too. You'll end up with a lot of nested try/catch blocks :(
cwap
You should do Exception translation (to an Exception type appropriate to the level of abstraction) in your catch block. FYI: "Multi-catch" is supposed to be going into Java 7.
jasonnerothin
FYI: In C++, you can put multiple catches after a try to catch different exceptions.
RobH
For shrinkwrap software, you need to catch all exceptions. At least put up a dialog box that explains that the program needs to shut down, and here's something incomprehensible you can send in a bug report.
David Thornley
+29  A: 

Have you ever tried to debug a program raising five exceptions per second in the normal course of operation ?

I have.

The program was quite complex (it was a distributed calculation server), and a slight modification at one side of the program could easily break something in a totally different place.

I wish I could just have launched the program and wait for exceptions to occur, but there were around 200 exceptions during the start-up in the normal course of operations

My point : if you use exceptions for normal situations, how do you locate unusual (ie exceptional) situations ?

Of course, there are other strong reasons not to use exceptions too much, especially performance-wise

Brann
if you use exceptions for normal situations, how do you locate unusual (ie exceptional situations ? --> as in the example, Nothing stops you from catching the normal exceptions
Peter
Example : when I debug a .net program, I launch it from visual studio and I ask VS to break on all exceptions. If you rely on exceptions as an expected behaviour, I can't do that anymore (since it would break 5times/sec), and it's far more complicated to locate the problematic part of the code.
Brann
/me agrees. I've been there... i'm still there. And the guy who make FileNotFound get thrown internally for each resource lookup in CF needs to be shot.
Quibblesome
+1 for the bolded part.
Christopher W. Allen-Poole
+1 for pointing out you don't want to to create an exception haystack in which to find an actual exceptional needle.
Grant Wagner
don't get this answer at all, i think people misunderstand here It has nothing to do with debugging at all, but with design. This is circular reasoning in it's pures form i'm afraid. And your point is really besides the question like stated before
Peter
You can catch the expected exceptions for flow control AND catch the unexpected after the same try block, I don't see the problem to be honest.
Peter
@Peter :Debugging without breaking on exceptions is difficult, and catching all exceptions is painful if there are a lot of them by design. I think a design which makes debugging hard is almost partially broken (in other words, design HAS something to do with debugging, IMO)
Brann
Even ignoring the fact that most situations I want to debug don't correspond to exceptions being thrown, the answer to your question is: "by type", e.g., I'll tell my debugger to catch only AssertionError or StandardError or something that does correspond to bad things happening. If you have trouble with that, then how do you do logging -- don't you log by level and class, precisely so you can filter on them? Do you think that's a bad idea, too?
Ken
@Ken : let's say I rely here and there on NullReferenceException to handle my control flow. Do you advocate disabling nullref exception catching in your environment development? If you do so, what if an unexpected (ie, not used for regular control flow ) nullref exception is raised? You simply don't have any way to locate it easily (since if you catch nullref exceptions, you'll be stuck in endless loops raising nullref exceptions every few milliseconds for 'regular control flow reasons' ...
Brann
Brann: As I tried to say (but maybe wasn't very clear), type is important. Therefore, NullReferencException is probably a bad one to use for control flow. But that doesn't mean something like StopIteration or MildWarning would be bad.
Ken
@Ken: Unfortunately, most people relying on exceptions are re-using standard exceptions. Or, to be more specific, they let the CLR raise those exceptions (eg they don't test a variable for nullity, and handle the nullref if needed). That being said, even with user exceptions, my point still stands, unless you rely on a different exception type each time you need to raise one, which doesn't seem very convenient either ...
Brann
+2  A: 

I think that you can use Exceptions for flow control. There is, however, a flipside of this technique. Creating Exceptions is a costly thing, because they have to create a stack trace. So if you want to use Exceptions more often than for just signalling an exceptional situation you have to make sure that building the stack traces doesn't negatively influence your performance.

The best way to cut down the cost of creating exceptions is to override the fillInStackTrace() method like this:

public Throwable fillInStackTrace() { return this; }

Such an exception will have no stacktraces filled in.

lewap
The stacktrace also requires the caller to "know about" (i.e. have a dependency upon) all Throwables in the stack. This is a bad thing. Throw exceptions appropriate to the level of abstraction (ServiceExceptions in Services, DaoExceptions from Dao methods, etc). Just translate if necessary.
jasonnerothin
A: 

Since you formulated a hypothesis you should also cite corroborating evidence/reasons. Name one reason why your code is superior to a much shorter, self-documenting if statement.

Konrad Rudolph
Things are not always that simple. It could be that one had to perform a lot of computation in order to make sure that an exception will not be thrown. The same computation will be made a second time, to make things worse. And, if it is a checked exception, you'll have to catch it anyway.
Ingo
OK, omit checked exceptions for a second, they are another matter; if the validity computation is expensive/difficult, why not abstract it in another method that gets called appropriately, and preferrably only once. Anyway, I'm not contesting the claim itself; I am contesting this particular example
Konrad Rudolph
(cont’d) and the onus is *not* on me to disprove an assertion I haven’t even made. It’s the other way round.
Konrad Rudolph
In this example, an IF is absolutely out of question. How is the client supposed to know whether an overflow will happen? This would mean he'd need detailed knowledge of the implementation of Date, TimeSpan and so on.
Ingo
But the code is *not* on the client side. It's inside the class' implementation (or rather, a derived class; here, the base class would have to offer an appropriate check method, as I've already mentioned). To repeat: I don't contest the validity of exceptions for flow control, only of the argument.
Konrad Rudolph
A: 

I feel that there is nothing wrong with your example. On the contrary, it would be a sin to ignore the exception thrown by the called function.

In the JVM, throwing an exception is not that expensive, only creating the exception with new xyzException(...), because the latter involves a stack walk. So if you have some exceptions created in advance, you may throw them many times without costs. Of course, this way you can't pass data along with the exception, but I think that is a bad thing to do anyway.

Ingo
Sorry, this is plain wrong, Brann. It depends on the condition. It's not always the case that the condition is trivial. Thus, an if statement could take hours, or days or even longer.
Ingo
In the JVM, that is. Not more expensive than a return. Go figure. But the question is, what would you write in the if statement, if not the very code that is already present in the called function to tell an exceptional case from a normal one --- thus code duplication.
Ingo
In this situation, I like the .net Double.TryParse approach. no code duplication, but no exceptions either.
Brann
So you advocate writing for each method xxx() (that could throw an exception) one accompagnying tryXxx() that does not, instead of try { xxx() ; } catch {}?
Ingo
no, that's not what I mean. I use double.TryParse only when I think an error can occur in the normal course operations (typically, when the data I'm Parsing has been input by the user. I advocate using exceptions only for exception situations.
Brann
The sentence: "Use exceptions only for exceptional situations" is pretty brain damaged until we agree what an exveptional situation is.So, the OO-foilk wisdom boils down to: "Use exceptions only for exceptional situations" and "An exceptional situation is one where you would throw exceptions."
Ingo
Ingo : an exceptional situation is one you don't expect. ie one you haven't thought of as a programmer. So my rule is "write code that doesn't throw exceptions" :)
Brann
This is a contradiction in itself. If one doesn't expect it, why should one write an exception handler or throw exceptions in the first place?
Ingo
I never write exception handlers, I always fix the problem (except when I can't do that because I don't have control over the faulting code). And I never throw exceptions, except when the code I wrote is intended for someone else to use (eg a library). No show me the contradiction ?
Brann
I agree with you to not throw exceptions wildly. But certainly, what is "exceptional" is a question of definition. That String.parseDouble throws an exception if it can't deliver a useful result, for example, is in order. What else should it do? Return NaN? What about non IEEE hardware?
Ingo
+3  A: 

The standard-google-anwser is that execptions are not regular and should be used in exceptional cases.

One reason, which is important to me, is that when I read a try-catch control structure in a software I maintain or debug, I try to find out why the original coder used an exception handling instead of an if-else structure. And I expect to find a good answer.

Remember that you write code not only for the computer but also for other coders. There is a semantic associated to an exception handler that you cannot throw away just because the machine doesn't mind.

mouviciel
+2  A: 

I don't really see how you're controlling program flow in the code you cited. You'll never see another exception besides the ArgumentOutOfRange exception. (So your second catch clause will never be hit). All you're doing is using an extremely costly throw to mimic an if statement.

Also you aren't performing the more sinister of operations where you just throw an exception purely for it to be caught somewhere else to perform flow control. You're actually handling an exceptional case.

Jason Punyon
+1  A: 

But you won't always know what happens in the Method/s that you call. You won't know exactly where the exception was thrown. Without examining the exception object in greater detail....

Adrian
A: 

Because SEH is expensive.

RaptorFactor
SEH isn't expensive at all since it essentialy describes a pttern. *Catching* an exception is where the expense comes in as the runtime has to do a lot of work to walk/unwind the stack, etc.
Scott Dorman
+3  A: 

The reason is simple: Since no-one else does, you shouldn't either. No existing code was intended to be used so, so your idiom would be incompatible with everyone else's.

Let's take your example as an example. It would break if you sent in a "negative" TimeSpan which would bring the DateTime to before DateTime.MinValue. You have no way of checking how the argument was out of range - was it too high, or too low? The exceptions don't provide enough granularity to figure out what happened in this case. They're just there to tell you that something happened, not exactly what happened.

Since compiler authors don't intend exceptions to be used for control flow, they optimize the non-exceptional case, as the exceptional case won't happen that often, and so, very small performance increases in the non-exceptional case are justified even if they damage the performance of the exceptional case by a great deal.

So basically; it slow for the computer to execute, and it confuses your peer programmers. Need any more reasons? :)


Edit

As for performance, exceptions aren't just "a little more expensive". They are extremely expensive. I wrote a little test:

    private static void TestExceptionPerformance()
    {
        const int Warmup = 20000, RealTest = 500000;
        var arr = new int[5];
        // Warmup
        Console.WriteLine("Warmup in {0}",
            RunArrayRangeCheckTest(Warmup, arr, CheckRangeWithLength<int>)
            + RunArrayRangeCheckTest(Warmup, arr, CheckRangeWithExceptions<int>)
            );
        // Real tests
        var durationLength = RunArrayRangeCheckTest(RealTest, arr, CheckRangeWithLength<int>);
        Console.WriteLine("Using length:     {0}", durationLength);
        var durationExceptions = RunArrayRangeCheckTest(RealTest, arr, CheckRangeWithExceptions<int>);
        Console.WriteLine("Using exceptions: {0}", durationExceptions);
        Console.WriteLine("Time diff (e/l): {0}", durationExceptions.Ticks / (decimal)durationLength.Ticks);
    }

    private static TimeSpan RunArrayRangeCheckTest<T>(int loops, T[] arr, Func<T[], int, bool> check)
    {
        var sw = Stopwatch.StartNew();
        for (int i = 0; i < loops; i++)
        {
            check(arr, (i % (arr.Length * 2)) - (arr.Length / 2));
        }
        sw.Stop();
        return sw.Elapsed;
    }

    private static bool CheckRangeWithLength<T>(T[] arr, int index)
    {
        return index >= 0 && index < arr.Length;
    }

    public static bool CheckRangeWithExceptions<T>(T[] arr, int index)
    {
        try
        {
            T whatever = arr[index];
            return true;
        }
        catch (IndexOutOfRangeException)
        {
            return false;
        }
    }

On my computer, I get the following result:

Using length:     00:00:00.0052855
Using exceptions: 00:00:11.0586295
Time diff (e/l): 2092,2579699176993661905212373

I.e., exceptions are more than 2000 times more expensive than using the non-exceptional approach. (My test is even a bit friendly to the exceptional case, as the overhead from the harness evens out the differences a little.) If you're looking at something that makes your program 2000+ slower without any added benefit, you've got some explaining to do.

gustafc
It is true that the example is not complete/correct. But the intent is sclear. So please tell me why the client should duplicate the computations (unknown to him), that are performed in the called code to tell an exceptional case from a normal one?
Ingo
If you don't understand the conditions that cause the exceptions, how do you know how to handle the exception? Nothing, other than completely swallowing it, and it's already a well-established fact that swallowing exceptions is usually a pretty bad thing to do.
gustafc
Your test is broken. Most likely, a new excption is made (with stack walk) each time. Don't confuse time to "create an exception object" and time to"throw and catch an exception".
Ingo
Yes, a new exception is made - that's my point. If you use exception-controlled flow with existing APIs, these APIs are going to create new exceptions. If you write new code with exception-controlled flow, it's an alien among existing code, with possibly equal performance. Lose/lose situation.
gustafc
Sure, but this example is about an existing API - the Date.add() will throw regardless if you want it. And no, you should not guess in your own code whether the called API may throw.
Ingo
+2  A: 

A first reaction to a lot of answers :

you're writing for the programmers and the principle of least astonishment

Of course! But an if just isnot more clear all the time.

It shouldn't be astonishing eg : divide (1/x) catch (divisionByZero) is more clear than any if to me (at Conrad and others) . The fact this kind of programming isn't expected is purely conventional, and indeed, still relevant. Maybe in my example an if would be clearer.

But DivisionByZero and FileNotFound for that matter are clearer than ifs.

Of course if it's less performant and needed a zillion time per sec, you should of course avoid it, but still i haven't read any good reason to avoid the overal design.

As far as the principle of least astonishment goes : there's a danger of circular reasoning here : suppose a whole community uses a bad design, this design will become expected! Therefore the principle cannot be a grail and should be concidered carefully.

exceptions for normal situations, how do you locate unusual (ie exceptional) situations ?

In many reactions sth. like this shines trough. Just catch them, no? Your method should be clear, well documented, and hounouring it's contract. I don't get that question I must admit.

Debugging on all exceptions : the same, that's just done sometimes because the design not to use exceptions is common. My question was : why is it common in the first place?

Peter
A: 

Lets assume you have a method that does some calculations. There are many input parameters it has to validate, then to return a number greater then 0.

Using return values to signal validation error, it's simple: if method returned a number lesser then 0, an error occured. How to tell then which parameter didn't validate?

I remember from my C days a lot of functions returned error codes like this:

-1 - x lesser then MinX
-2 - x greater then MaxX
-3 - y lesser then MinY

etc.

Is it really less readable then throwing and catching an exception?

kender
that's why they invented enums :)But magical numbers is a completely different topic.. http://en.wikipedia.org/wiki/Magic_number_(programming)#Unnamed_numerical_constant
Isak Savo
+1  A: 

Because the code is hard to read, you may have troubles debugging it, you will introduce new bugs when fixing bugs after a long time, it is more expensive in terms of resources and time, and it annoys you if you are debugging your code and the debugger halts on the occurence of every exception ;)

Gambrinus
+1  A: 

Typically there is nothing wrong, per se, with handling an exception at a low level. An exception IS a valid message that provides a lot of detail for why an operation cannot be performed. And if you can handle it, you ought to.

In general if you know there is a high probability of failure that you can check for... you should do the check... i.e. if(obj != null) obj.method()

In your case, i'm not familiar enough with the C# library to know if date time has an easy way to check whether a timestamp is out of bounds. If it does, just call if(.isvalid(ts)) otherwise your code is basically fine.

So, basically it comes down to whichever way creates cleaner code... if the operation to guard against an expected exception is more complex than just handling the exception; than you have my permission to handle the exception instead of creating complex guards everywhere.

Add'l point: If your Exception provides failure capture information (a getter like "Param getWhatParamMessedMeUp()"), it can help the user of your API make a good decision about what to do next. Otherwise, you're just giving a name to an error state.
jasonnerothin
A: 

How about performance? While load testing a .NET web app we topped out at 100 simulated users per web server until we fixed a commonly-occuring exception and that number increased to 500 users.

James Koch
A: 

Josh Bloch deals with this topic extensively in Effective Java. His suggestions are illuminating and should apply to .Net as well (except for the details).

In particular, exceptions should be used for exceptional circumstances. The reasons for this are usability-related, mainly. For a given method to be maximally usable, it's input and output conditions should be maximally constrained.

For example, the second method is easier to use than the first:

/**
 * Adds two positive numbers.
 *
 * @param addend1 greater than zero
 * @param addend2 greater than zero
 * @throws AdditionException if addend1 or addend2 is less than or equal to zero
 */
int addPositiveNumbers(int addend1, int addend2) throws AdditionException{
  if( addend1 <= 0 ){
     throw new AdditionException("addend1 is <= 0");
  }
  else if( addend2 <= 0 ){
     throw new AdditionException("addend2 is <= 0");
  }
  return addend1 + addend2;
}

/**
 * Adds two positive numbers.
 *
 * @param addend1 greater than zero
 * @param addend2 greater than zero
 */
public int addPositiveNumbers(int addend1, int addend2) {
  if( addend1 <= 0 ){
     throw new IllegalArgumentException("addend1 is <= 0");
  }
  else if( addend2 <= 0 ){
     throw new IllegalArgumentException("addend2 is <= 0");
  }
  return addend1 + addend2;
}

In either case, you need to check to make sure that the caller is using your API appropriately. But in the second case, you require it (implicitly). The soft Exceptions will still be thrown if the user didn't read the javadoc, but:

  1. You don't need to document it.
  2. You don't need to test for it (depending upon how aggresive your unit testing strategy is).
  3. You don't require the caller to handle three use cases.

The ground-level point is that Exceptions should not be used as return codes, largely because you've complicated not only YOUR API, but the caller's API as well.

Doing the right thing comes at a cost, of course. The cost is that everyone needs to understand that they need to read and follow the documentation. Hopefully that is the case anyway.

jasonnerothin
A: 

If you are using exception handlers for control flow, you are being too general and lazy. As someone else mentioned, you know something happened if you are handling processing in the handler, but what exactly? Essentially you are using the exception for an else statement, if you are using it for control flow.

If you don't know what possible state could occur, then you can use an exception handler for unexpected states, for example when you have to use a third-party library, or you have to catch everything in the UI to show a nice error message and log the exception.

However, if you do know what might go wrong, and you don't put an if statement or something to check for it, then you are just being lazy. Allowing the exception handler to be the catch-all for stuff you know could happen is lazy, and it will come back to haunt you later, because you will be trying to fix a situation in your exception handler based on a possibly false assumption.

If you put logic in your exception handler to determine what exactly happened, then you would be quite stupid for not putting that logic inside the try block.

Exception handlers are the last resort, for when you run out of ideas/ways to stop something from going wrong, or things are beyond your ability to control. Like, the server is down and times out and you can't prevent that exception from being thrown.

Finally, having all the checks done up front shows what you know or expect will occur and makes it explicit. Code should be clear in intent. What would you rather read?

Not true at all : " Essentially you are using the exception for an else statement, if you are using it for control flow. " If you use it for control flow, you know what you catch exactly and never use a general catch, but a specific one of course!
Peter
A: 

You might be interested in having a look at Common Lisp's condition system which is a sort of generalization of exceptions done right. Because you can unwind the stack or not in a controlled way, you get "restarts" as well, which are extremely handy.

This doesn't have anything much to do with best practices in other languages, but it shows you what can be done with some design thought in (roughly) the direction you are thinking of.

Of course there are still performance considerations if you're bouncing up and down the stack like a yo-yo, but it's a much more general idea than "oh crap, lets bail" kind of approach that most catch/throw exception systems embody.

simon
+1  A: 

I don't think there is anything wrong with using Exceptions for flow-control. Exceptions are somewhat similar to continuations and in statically typed languages, Exceptions are more powerful than continuations, so, if you need continuations but your language doesn't have them, you can use Exceptions to implement them.

Well, actually, if you need continuations and your language doesn't have them, you chose the wrong language and you should rather be using a different one. But sometimes you don't have a choice: client-side web programming is the prime example – there's just no way to get around JavaScript.

An example: Microsoft Volta is a project to allow writing web applications in straight-forward .NET, and let the framework take care of figuring out which bits need to run where. One consequence of this is that Volta needs to be able to compile CIL to JavaScript, so that you can run code on the client. However, there is a problem: .NET has multithreading, JavaScript doesn't. So, Volta implements continuations in JavaScript using JavaScript Exceptions, then implements .NET Threads using those continuations. That way, Volta applications that use threads can be compiled to run in an unmodified browser – no Silverlight needed.

Jörg W Mittag
A: 

Apart from the reasons stated, one reason not to use exceptions for flow control is that it can greatly complicate the debugging process.

For example, when I'm trying to track down a bug in VS I'll typically turn on "break on all exceptions". If you're using exceptions for flow control then I'm going to be breaking in the debugger on a regular basis and will have to keep ignoring these non-exceptional exceptions until I get to the real problem. This is likely to drive someone mad!!

Sean
I already handeld that one higer : Debugging on all exceptions : the same, that's just done because the design not to use exceptions is common. My question was : why is it common in the first place?
Peter
A: 

You can use a hammer's claw to turn a screw, just like you can use exceptions for control flow. That doesn't mean it is the intended usage of the feature. The if statement expresses conditions, whose intended usage is controlling flow.

If you are using a feature in an unintended way while choosing to not use the feature designed for that purpose, there will be an associated cost. In this case, clarity and performance suffer for no real added value. What does using exceptions buy you over the widely-accepted if statement?

Said another way: just because you can doesn't mean you should.

Bryan Watts