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
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
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.
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)
'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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With