Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mixing errors and exceptions in C#

I have looked, but couldn't find a definitive answer for some of my exception questions, especially regarding C# best practices.

Perhaps I will always be confused about the best way to use exceptions, I ran across this article which basically says 'always use exceptions, never use error codes or properties' http://www.eggheadcafe.com/articles/20060612.asp. I'll definitely buy that, but here's my dilemma:

I have a function 'caller' which calls 'callee'. 'callee' performs a few different things, each of which might throw the same type of exception. How do I relay meaningful information back to 'caller' about what 'callee' was doing at the time of the exception?

I could throw a new exception like below, but I'm worried I'll mess up the stacktrace which is bad:

//try to log in and get SomeException  
catch(SomeException ex)
{
  throw new SomeException("Login failed", ex);
}

...

//try to send a file and get SomeException
catch(SomeException ex)
{
    throw new SomeException("Sending file failed", ex):
}

Thanks, Mark

like image 501
MStodd Avatar asked Jan 19 '12 18:01

MStodd


4 Answers

There is no single best practice to cover all scenarios in .Net. Anyone who says "always use exceptions" or "always use error codes" is simply wrong. Programs written in .Net are to broad and complex to generalize into a hard and fast rule like that.

There are many cases where exceptions simply aren't appropriate. For example if I have a very tight loop looking up values in a Dictionary<TKey, TValue> i would absolutely prefer TryGetValue over a throwing indexer. Yet in other cases I would prefer the throw if the data provided to me was contracted to already be in the map.

The best way to approach this decision is on a case by case basis. In general I only use Exceptions if the situation is truly exceptional. One essentially that couldn't be predicted by the caller or results from the caller explicitly violating a contract. Examples

  • Can't be predicted: File not found
  • Contract Violation: Passing a negative index into an indexer
like image 169
JaredPar Avatar answered Nov 11 '22 23:11

JaredPar


The caller doesn't need to know what the callee was doing at the time of the exception. It shouldn't know anything about how the callee is implemented.

like image 35
John Saunders Avatar answered Nov 11 '22 22:11

John Saunders


In scenarios like this I usually inject a logger and log the specific error and rethrow the original exception:

//try to log in and get SomeException  
catch(SomeException ex)
{
    logger.LogError("Login failed");
    throw;
}

...

//try to send a file and get SomeException
catch(SomeException ex)
{
    logger.LogError("Sending file failed");
    throw;
}

The throw; will keep the original stack trace alive (as opposed to throw ex; which will create a new stacktrace).

Edit

Depending on what your actual code is doing it could make sense to actually break callee up into several calls (Login(), SendFile(), etc.), so caller is performing the individual steps instead of calling one big method which is doing everything. Then the caller will know where it failed and can act upon it (maybe ask the user for different login credentials)

like image 3
ChrisWue Avatar answered Nov 11 '22 23:11

ChrisWue


'callee' performs a few different things, each of which might throw the same type of exception.

I think this is the real culprit: callee should be throwing either a different type of exception based on kind of failure has happened, or the exceptions of the same type should carry enough additional information to let the caller figure out how to handle this particular exception. Of course if the caller is not intended to handle the exception at all, it shouldn't be in the business of catching it in the first place.

like image 2
Sergey Kalinichenko Avatar answered Nov 11 '22 23:11

Sergey Kalinichenko