Is it bad to use exceptions to end function? [closed]

点点圈 提交于 2019-12-25 12:26:12

问题


I have an App where I use a lot of Exceptions.

Recently I heard that Exceptions cost a lot in terms of performance.

My App looks like this:

Try
{
    Function1();
    Function2();
    Function3();
    Function4();
}

catch(Execption ex)
{
    //I return to the user the error (ex) that happen inside the 
    //function that fails
}

Each of my functions 1,2,3 etc look similar to this..

Void Function1()
{
    //Do something...
    //If something fail
    Throw New Exception("Fails because bla bla");

    //Do something...
    //If something fail
    Throw New Exception("Fails because bla bla bla bla");

    //If everything its ok, just continue without throwing anything
}

Is this bad design?
Will this hurt my App performance?


回答1:


When exceptions are thrown they rebuilt the stack trace among other things. This is pretty costly. If you can, try to prevent a known error condition like this (here C-style):

public static const int INVERSE_DIVISION_BY_ZERO = -1; // any value not possible on correct operation will do

public int Inverse(int a)
{
    if (a != 0)
    {
        return 1 / a;
    }

    return INVERSE_DIVISION_BY_ZERO;
}

Now, this example is ugly I know. It doesn't help much.

In fact from testing first:

if (a != 0)
{
    b = Inverse(a);
}

It is now a matter of testing later:

b = Inverse(a);
if (b != Inverse.INVERSE_DIVISION_BY_ZERO)
{
    // safe to go
}

Does this make sense? No. The example is quite poor. But it shows that there is a minimum amount of testing to do to keep code execution safe. If it's not done before, it has to be done later, but can't really be avoided.

Exceptions should be thrown for error conditions that are exceptional in a sense that you can't control them like no CD in drive and similar. When you already know how the code fails, prevent it!

I want to add this:

Exception handling is a complex design problem not just an implementation problem. Their is a trade-off to take care off, between these two extremes:

  • clean, readable code that throws exceptions on occasion;
  • efficient code that is difficult to read but prevents exceptions and returns C-style error codes that need interpretation.

The common C# practice is to favor clean, readable code over premature optimization, and I share this vision.

But this does not mean that Exceptions should be deliberately thrown. There are cases where intentional throwing makes perfect sense, for example:

enum Gender
{
    Unspecified,
    Male,
    Female
}

// later in the code

switch (gender)
{
    case Gender.Unspecified:
        // handle
        break;
    case Gender.Male:
        // handle
        break;
    case Gender.Female:
        // handle
        break;
    default:
        throw new ArgumentException(string.Format("Unrecognized gender (was {0})", (int)gender));
}

The undefined gender can't be rendered as a string because it is not defined. It will be rendered as an int value, instead.

Now this example is in my opinion clean readable code that is also robust when the Gender enum is modified in future times. At least it will tell the developer that he forgot something...

Another example is this:

// A: high performance, let it throw
for (i = 0; i < values.length; i++)
{
    values[i] = 1 / values[i];
}

// B: slow performance, test first
for (i = 0; i < values.length; i++)
{
    if (values[i] != 0)
    {
        values[i] = 1 / values[i];
    }
}

When values[i] is 0 A will fail while B will ignore that spot in the array. Now I wonder about this:

  • is the array useful with unhandled spots? maybe it should be thrown away at that point;
  • is it really more performant to test instead of throw an exception?
  • what if 0 is so seldom it happens once every 1000 years (really)? That's like saying never, but based on probabilistic estimations.
  • maybe testing in each cycle for something that most probably will not happen is a waste...

If there is solid data to show that error conditions are extremely rare they should be handled with exceptions, because testing will cost much more on the average.

This doesn't mean you don't handle the exceptional state, it just means you handle it in a non-efficient way because it's rare and testing beforehand is costly.

EDIT: added error condition

EDIT 2: added some more thoughts




回答2:


You should use return; when you want to stop the execution of a method at some point.

Exceptions and exception catch are used when you want to localize also the reason why something went wrong with a piece of code. By finding out what type of exception occured, you can take appropiate measures.




回答3:


No, throwing exceptions upon -well- exceptional states is good design.

On the other side I have seen code that uses exceptions excessively to basically communicate function results back to the caller. This is bad design, which can easily be seen by the fact that those exceptions are not thrown in exceptional states but rather during regular operation and at a high frequency.




回答4:


Exceptions are for Exceptional cases.

If you for example want to validate an email address, you write an Email validator.

public bool Validate(string emailAddr)
{
    // Logic
    return false; // validation failed.
}

Then in your main logic you can write:

if(Validate(emailInpunt))
{
    // Do stuff.

}

This way your code becomes very readable.

If you use exceptions it would look like:

try
{
    Validate(emailInpunt);
}
catch
{
     // Something
}

Already in the above example, the code is harder to read, and it will be a bit harder to control the flow, if you want to add different cases, fx. Validate Email, OR check some value that says it should ignore it.

Also, nesting tons of try catches, is harder to read.

try
{
    Validate(emailInpunt);

    try
    {
        DoSomething(otherStuff);
    }
    catch
    {
         // Something
    }

}
catch
{
     // Something
}

And as you mentioned, Exceptions are expensive, because it builds a giant stacktrace, and generally halts the entire program.

Example of proper Exception use

try
{
    SqlConnection con = new SqlConnection(....);
    // Do stuff with the database connection

}
catch(SqlException sex)
{
     // Log this
     throw new UserSomethingException("A connection to the database could not be established");
}

Exceptions as Assertions
Exceptions are also used to tell the developer about a programming error.

Consider this:

public double Calculate(MeaningOfLifeTheUniverseAndEverythingQuestion bigQuestion)
{
     if(bigQuestion == null)
         throw new ArgumentException("MeaningOfLifeTheUniverseAndEverythingQuestion cannot be null!!");

     //  7½ million years of computing
     return 42;
}

In this case, we throw an error, letting the programmer know he has made an error in his code.



来源:https://stackoverflow.com/questions/21370622/is-it-bad-to-use-exceptions-to-end-function

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!