Reputation: 42340
I want to implement custom exception handling in my library so that I know where an exception occurred, so I am doing this:
try
{
DoSomething();
}
catch(Exception ex)
{
//LibraryException refers to any exception in the libraries exception hierarchy
throw new LibraryException(ex.Message, ex);
}
Should this be avoided?
Does it have any performance implications?
What are the implications of catching, nesting and re-throwing exceptions?
Upvotes: 2
Views: 7248
Reputation: 1488
Ok, so as a real quick overview, when an exception is caught in a try catch block, it has to gather then entire stack for the trace. Throwing any type of exception is actually rather expensive, but it gets exponentially so when you nest throws inside of catch blocks. So really you should only throw an exception if you know exactly why you are throwing it and plan on handling it through a try. This is mostly the case when you are creating an API, and cannot predict how another developer may use your library.
If you are writing for your own application, you should avoid throwing an exception at all, since you are just throwing it to yourself (basically). In that case, you should be handling what happens if an exception is thrown not throw your own.
Unlike Python (which I like but different paradigm) and other "oops" languages, it is not good practice to control flow through exception handling in C#.
Under C# how much of a performance hit is a try, throw and catch block
Arguments for or against using try catch as logical operators
C# Exception (Check this one out)
CA1031: Do not catch general exceptions
Upvotes: 1
Reputation: 124766
The only potential problem is that you're catching a non-specific Exception
, so not conforming to the exception handling guidelines.
One of the following would be more conformant with these guidelines:
try
{
DoSomething();
}
catch(SomeException ex)
{
throw new LibraryException(ex.Message, ex);
}
or:
try
{
DoSomething();
}
catch(Exception ex)
{
if (ex is SomeException || ex is SomeOtherException)
{
throw new LibraryException(ex.Message, ex);
}
throw;
}
As for performance, once an Exception has been thrown, something exceptional has happened, and you probably don't care about the small additional overhead of wrapping it.
From comments:
in most cases when a library chooses to wrap exceptions it will wrap all exceptions that are thrown outside of the scope of the library, ...
I disagree with this, though it's admittedly subjective. One example of a library that wraps exceptions is SqlMembershipProvider
, which wraps some specific exceptions in a ProviderException
, e.g.:
try
{
new Regex(this._PasswordStrengthRegularExpression);
}
catch (ArgumentException exception)
{
throw new ProviderException(exception.Message, exception);
}
but other exceptions such as SqlException
that a caller can't be expected to handle are propagated unwrapped.
Upvotes: 4
Reputation: 10184
In context, throwing a more specific exception is generally a good idea, provided that LibraryException comes from your own problem domain and provides more specific information to a developer such that they can say "Ah, a Library exception means that one of a certain class of errors occurred."
try-catches do impose their own performance overhead, but I see nothing that makes this block substantially worse than any other similar block.
Upvotes: 1
Reputation: 203840
Should this be avoided?
That's a matter of preference. In some situations it can be advantageous, in some detrimental, and in most cases some of both. There are cases where you see this done by existing libraries, and there are other libraries that choose not to.
Does it have any performance implications?
Probably, yes, but I doubt it's real significant. It's not exactly cheap to begin with.
What are the implications of catching, nesting and re-throwing exceptions?
advantages:
disadvantages:
Upvotes: 2
Reputation: 33149
This is a good practice, if it adds abstraction and/or clarity to your architecture.
It makes the exception more explicit, and may hide lower-layer details from higher layers. For instance, in a Data Access Layer you may catch SqlExceptions and throw DataAccessExceptions instead, so that the higher layers do not "know" you are using SQL Server as your data store.
Upvotes: 2