Exception vs. if statements [duplicate] - c#

This question already has answers here:
Is it "bad" to use try-catch for flow control in .NET?
(8 answers)
Closed 8 years ago.
I have 2 pieces of code. What would say is best practice and why?
In the first version I add a new shop and evaluate if it's successful with Exceptions, and in the second version I do the same with "if" statements.
I've recently read that Exceptions can be expensive in the code, and if all "Add" method is implemented this way it can cause performance issues.
Can anybody confirm this?
Thanks!!!
public bool AddShop1(Shop newShop)
{
try
{
ShopDictionary.Add(newShop.ShopId, newShop);
return true;
}
catch (ArgumentNullException)
{
return false;
}
catch (ArgumentException)
{
return false;
}
}
public bool AddShop2(Shop newShop)
{
if (newShop == null || ShopDictionary.ContainsKey(newShop.ShopId))
{
return false;
}
ShopDictionary.Add(newShop.ShopId, newShop);
return true;
}

you should not use try catch for the control flow logic.
that should be done using if or switches etc.
try catch should be used for uncertain situations only, and should then be handled accordingly.

It depends from how often your function will cause exception. If exceptions will happen rarely (once per 1000 calls), then you can ignore slowdown of performance. But if from 1000 executions you'll get 800 exceptions, then definitely convert to ifs. But then just a question, if from 1000 you have 800 exceptions, is it really exception, or a rule of business logic?

Well, avoiding exception is more preferred for the performance for your application. and if you really interested in exception, you can do like this way,
public bool AddShop2(Shop newShop, out Exception exception)
{
exception = null;
try
{
if (newShop == null || ShopDictionary.ContainsKey(newShop.ShopId))
{
return false;
}
ShopDictionary.Add(newShop.ShopId, newShop);
}
catch (Exception ex)
{
exception = ex;
}
return true;
}

Related

Try Catch to Handle Exception [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I am trying to update some documents in DocumentDb / CosmosDb, and if that fails, need to do something else, and then if that fails to log it out...
try {
do a thing w/ database
}
catch (DocumentClientException dce1) {
try {
do another, alternative thing w/ database
}
catch (DocumentClientException dce2) {
log to app insights.
}
}
I'm not sure about this, it seems clunky.. what do you guys think?
For additional bonus points, I need to do this quite frequently.. so something that I can farm off somewhere would be even better ;)
Personally I'd avoid intermixing exception flow with a functional logic flow. It can get brittle. Instead, convert the exception into a logical flag and use it in ordinary logic constructs.
So step 1 is catch the exception and set a variable or return value based on it, and wrap this in an independent method to mask the messiness from everyone else:
bool TryDoSomethingWithDataBase()
{
try
{
//Do thing that could fail
return true;
}
catch(SpecificException ex)
{
return false;
}
}
bool TryDoSomethingElseWithDataBase()
{
try
{
//Do thing that could fail
return true;
}
catch(SpecificException ex)
{
return false;
}
}
Step 2 is to write the logic as usual:
if (!TryDoSomethingWithDatabase())
{
if (!TryDoSomethingElseWithDatabase())
{
LogFatalError();
}
}
Or
var ok = TryDoSomethingWithDatabase();
if (ok) return;
ok = TryDoSomethingElseWithDatabase();
if (ok) return;
LogFatalError();
Why would your thing with the Database fail? You would be better coding for the conditionals you are aware of and expecting and do different things if you want to go into a different logic for processing the result.
Try catch will catch anything and everything, so if your connection to the db fails etc or if you are trying to read or insert malformed data etc.
Try catch does have various exceptions that you can investigate further and catch the specific exception you are interested in.. e.g.
try
//try something
catch (Exception ex)
{
if (ex is FormatException || ex is OverflowException)
{
//Do something specific;
return;
}
throw;
}
This is ok but if you say you'll have this over and over it's better to extract that logic and reuse it.
One way of doing this is to have a method that accept the first and section actions as parameters, for example:
public void TryThis(Action doFirst, Action doSecond)
{
try {
doFirst();
}
catch (DocumentClientException dce1) {
try {
doSecond();
}
catch (DocumentClientException dce2) {
log to app insights.
}
}
}
And then use it like so:
public void DoSomethig1()
{
...
}
public void DoSomething2()
{
...
}
TryThis(DoSomething1, DoSomething2)

How to treat and test flow control if not with exceptions with c#?

What's the right way to treat and test flow control on methods that are void if not with exceptions? I've seen that Microsoft do not recomend such practice so what's the right way?
This is how how I'm treating parameters that shouldn't be accepted in my method:
public void RentOutCar(ReservationInfo reservationInfo)
{
try
{
if (string.IsNullOrEmpty(reservationInfo.ReservationNumber) || string.IsNullOrWhiteSpace(reservationInfo.ReservationNumber))
{
throw new ArgumentException("Reservation Number is null or empty.");
}
if (reservationInfo == null)
{
throw new ArgumentNullException("Null Reservation info.");
}
if (reservationInfo.Car == null)
{
throw new ArgumentNullException("No car registered to rent.");
}
if (reservationInfo.RentalDatetime == DateTime.MinValue || reservationInfo.RentalDatetime == DateTime.MaxValue)
{
throw new ArgumentException("Rental Date has an unreal value.");
}
if (reservationInfo.Car.Mileage <0)
{
throw new ArgumentOutOfRangeException("Mileage can't be less than 0.");
}
reserverationsRegister.ReservationsDone.Add(reservationInfo);
}
catch (Exception)
{
throw;
}
}
This is not what Microsoft mean when they say you should not control flow with exceptions.
While the use of exception handlers to catch errors and other events
that disrupt program execution is a good practice, the use of
exception handler as part of the regular program execution logic can
be expensive and should be avoided.
In other words, you should not throw (and subsequently catch) exceptions in situations where the code in the try block is likely to throw and represents legitimate program logic.
A contrived example of controlling flow with exceptions may look like:
int x = GetUserInput();
try
{
MustAcceptPositiveInput(x);
}
catch (InputIsNonPositiveException)
{
MustAcceptNonPositiveInput(x);
}
The equivalent 'correct' code may look like:
int x = GetUserInput();
if (x > 0)
{
MustAcceptPositiveInput(x);
}
else
{
MustAcceptNonPositiveInput(x);
}
Exceptions should be reserved for exceptional situations, those which are not part of expected program execution. It results in more readable, less surprising and more performant code.
What you are doing in your code is fine (except for the redundant try-catch and faulty order of tests as #Clay mentions), you are validating inputs for exceptional values, those which your code was not meant to handle.
Throwing an exception if the inputs are not valid is fine. Test reservationInfo for null first - or your other tests will break in unexpected ways. Also - no point in wrapping your tests in a try/catch if all you're going to do is rethrow it.
This is not a "control flow" issue as described in the article you put in the comments - and throwing exceptions is appropriate here.
You might consider wrapping just the "working code" in a try/catch, but only if you can recover from (or maybe log) any exceptions:
try
{
reserverationsRegister.ReservationsDone.Add(reservationInfo);
}
catch( Exception ex )
{
LogError( ex );
throw;
}

Is it good to use try catch within a try catch? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Are nested Try/Catch blocks a bad idea?
Currently I am using try catch within try catch ? The current senario requires it in our application.
void MyFun()
{
try
{
//Process logic 1
// ......
try
{
//Process logic 2
// ......
} catch (Exception ex)
{
//write an error details in database
}
//Process Logic 3
// ......
} catch (Exception ex)
{
//show error msg
}
}
No particular problem with this especially if you want to handle the exceptions differently.
However, if the inner exception and the outer exception are of different types E1, E2 respectively and E1 is not a parent of E2, you can have two adjacent catch clauses.
try
{
// do something
}
catch (E1 e1)
{
}
catch (E2 e2)
{
}
As noted by Rob and J.Steen - this is slightly different than the case in the question as in this case is E1 is thrown the code after it will not be executed.
A nested try/catch is fine. what you want to stay away from is changing the logical flow of your code based on the try catch. In other words, you shouldn't treat a try/catch as an if/else block. so this isn't ideal:
//over the top example just to demonstrate my point
public bool IsNumberTen(int x)
{
try
{
if(x > 10)
throw new NumberTooHighException();
else if(x < 10)
throw new NumberTooLowException();
else
return true;
}
catch(NumberTooHighException)
{
return false;
}
catch(NumberTooLowException)
{
return false;
}
}
This item suggests that its not a bad thing and that you would only have to handle the error in another way any way.
Exception handling try catch inside catch
I don't see why not. If you have logic in the catch which may fail or raise an exception that requires handling then it makes sense.
Its a little difficult to answer this question without knowing what logic is in here.
Certainly in terms of performance, nested exception handling will incur a greater cost, but general rule of thumb is only catch exceptions that you as a developer understand how to handle. This overlaps into the practice of TDD where if you have a good enough set of tests you can identify where the expected exceptions should be, then this will dictate your exception logic.
I would say this: it's not bad. Whether it's good depends on your program, and whether such a concept makes sense given your method's logic and contracts.
Edit: I'd suggest checking out the article Exception Cost: When to throw and when not to. It outlines what is most expensive for exception management in the CLR.
I am trying to think of situations where you may want a nested block... perhaps if you are making database changes and you are using the try catch as a virtual transaction, you may want to try to update some properties but then carry on if that fails, but also catch an overall exception if and when you actually commit to the database update itself.
Even with this considered, you should never need to do this... It should be perfectly sufficient to simply stack blocks next to each other like so:
void MyFun()
{
try
{
//Process logic 1
// ......
} catch (Exception ex)
{
//show error msg
}
try
{
//Process logic 2
// ......
} catch (Exception ex)
{
//write an error details in database
}
}
It is also probably worth noting that if you find the need to nest try catch blocks then there is probably a better way you could be designing your code.
EDIT: Itay's answer is also somewhat better than nesting, although it will not allow you to carry on in the block once you have caught an exception.
Hope this helps!

How to rethrow a prior exception from inside a nested try-catch block? (C#)

I have code that attempts a type conversion. If it fails, I want to try something else, and if that also fails, then rethrow the original exception attempted by the first conversion. The problem is that the only way I know of to rethrow is to have 'throw;' sitting at the end of the catch block. What happens when I only want the rethrow to happen from within another catch block?
try
{
valueFromData = Convert.ChangeType(valueFromData, pi.PropertyType);
}
catch(InvalidCastException e)
{
Debug.WriteLine(String.Concat("Info - Direct conversion failed. Attempting to convert using String as an intermidiate type."));
try { valueFromData = Convert.ChangeType(valueFromData.ToString(), pi.PropertyType); }
catch { throw e; }
}
As you can see above, I have to use 'throw e;', which resets the call stack.
Only workaround I've though of so far is (imo) gross:
bool handled = true;
...
catch { handled = false; }
if( !handled ) throw;
There is no way to rethrow an exception from an outer catch block inside an inner catch block. The best way to achieve this pattern is to note whether or not the inner operation succeeded
catch (InvalidCastException e) {
bool threw = false;
try {
...
} catch {
threw = true;
}
if (threw) {
throw;
}
}
If you are intending to make multiple attempts at conversion then it certainly makes sense to use non-throwing operations where applicable so that you sidestep the problem entirely.
Supposing that's not possible for the sake of argument, the next step is to question the throw e; approach. In the example code you give, IMHO there is no problem at all if your throw resets the call stack. Once someone gets to the source code for this method (which the modified call stack would still point to), I think it's pretty obvious what's going on. So while resetting the call stack is always a questionable decision, in this particular case it should be allowed to happen because there would be no tangible drawback.
Finally, the workaround you mention is interesting as well as gross (agree on that!).
I tried the following and it seems to achieve your goal, when the 2nd exception occurs (in this case, the ArgumentException) it throws the first exception (InvalidCastException)
[TestMethod]
[ExpectedException(typeof(InvalidCastException))]
public void ReThrowException() {
var ret = false;
try {
ret = F1(1);
}
catch (InvalidCastException ex) {
try {
ret = F1(2);
}
catch (Exception e) {
Debug.WriteLine(e.Message);
throw ex;
}
}
}
private bool F1(int i) {
if (i == 1) {
throw new InvalidCastException();
} else {
throw new ArgumentException();
}
return false;
}
Hope this helps,
Alan.

try- catch. Handling multiple exceptions the same way (or with a fall through)

There has already been a question posted here which is very similar. Mine is extending that question a bit more. Say you want to catch multiple types of exception but want to handle it the same way, is there a way to do something like switch case ?
switch (case)
{
case 1:
case 2:
DoSomething();
break;
case 3:
DoSomethingElse()
break;
}
Is it possible to handle few exceptions the same way . Something like
try
{
}
catch (CustomException ce)
catch (AnotherCustomException ce)
{
//basically do the same thing for these 2 kinds of exception
LogException();
}
catch (SomeOtherException ex)
{
//Do Something else
}
Currently there is no language construct to accomplish what you want. Unless the exception all derive from a base exception you need to consider refactoring the common logic to a method and call it from the different exception handlers.
Alternatively you could do as explained in this question:
Catch multiple Exceptions at once?
Personally I tend to prefer the method-based approach.
You should really have a BaseCustomException and catch that.
This is copied from another posting, but I am pulling the code to this thread:
Catch System.Exception and switch on the types
catch (Exception ex)
{
if (ex is FormatException || ex is OverflowException)
{
WebId = Guid.Empty;
return;
}
throw;
}
I prefer this to repeating a method call in several catch blocks.
In vb.net, one can use exception filters to say, e.g.
Catch Ex As Exception When TypeOf Ex is ThisException Or TypeOf Ex is ThatException
Unfortunately, for whatever reasons, the implementors of C# have as yet refused to allow exception filtering code to be written within C#.
You shouldn't be catching this many custom exceptions,however if you want you can create a common BaseException and catch that.
I've never actually done this or anything like it, and I don't have access to a compiler for testing purposes but surely something like this would work. Not sure how to actually do the type comparison or if C# would let you replace the if statements with a case statement.
try
{
}
catch (System.Object obj)
{
Type type;
type = obj.GetType() ;
if (type == CustomException || type == AnotherCustomException)
{
//basically do the same thing for these 2 kinds of exception
LogException();
}
else if (type == SomeOtherException ex)
{
//Do Something else
}
else
{
// Wasn't an exception to handle here
throw obj;
}
}

Categories

Resources