How can I throw exception gracefully?
public void Test()
{
if (error != 0) {
string msg = "Error";
throw new Exception(msg);
}
// Other function
...
}
I have also change the throw new Exception(msg); with logger
public void Test()
{
if (error != 0) {
string msg = "Error";
//throw new Exception(msg);
logger.Error(msg);
}
// Other function
...
}
Should I use Exit function to exit the function when error hit?
Thnak you.
You want to log before you throw the exception.
You also want to throw an exception type that inherits from System.Exception so consumers can catch specific types.
Throwing the exception will exit the function (actually will process a finally block first if you have one) so you only need to throw.
Also, if you're catching a different exception in an error condition, you can log and then simply call throw; to throw the original exception and not trash the stack. If you want to throw your own
exception type in that case, you can include the original exception as the inner exception
catch (Exception e)
{
// log exception details
throw;
}
or ...
catch (Exception e)
{
// log exception details
throw new MyCustomException("message", e); // inherits from Exception
}
The benefit of the last one (if applicable) is the consumer can catch MyCustomException if it's interesting for special handling.
The intention for exceptions is to be 'ungraceful', if you will. Don't call Exit, unless it is truly fatal and you do not want the program to continue. Client code should catch the exception, and evaluate whether or not to exit.
Also, if you want to log the error, do it before you throw.
ps. don't name your functions after keywords ....
Related
This question already has answers here:
Why catch and rethrow an exception in C#?
(17 answers)
Closed 6 years ago.
I have some code which catches the exception, rolls back the transaction and then rethrow the exception.
catch ( Exception exSys ) {
bqBusinessQuery.RollBackTransaction();
throw exSys ;
}
If I use this code, VS Code analysis throws warning saying
Use 'throw' without an argument instead, in order to preserve the stack location where the exception was initially raised.
If I use the code
catch ( Exception exSys ) {
bqBusinessQuery.RollBackTransaction();
throw;
}
then I get a warning saying
The variable 'exSys' is declared but never used
How should I solve this problem?
Edit
I tried this method, but it doesn't work. system.exception class requires an extra message, along with inner exception. If I do that, it will throw a new message overriding the message from the original exception. I don't want to get the new exception, I want to throw the same exception with same message.
catch (System.Exception ex)
{
throw new System.Exception(ex);
}
Edit
catch (System.Exception ex)
{
throw new System.Exception("Test",ex);
}
Tried this method. And then manually caused an exception using throw new Exception("From inside");. Now, ex.Message returns "Test" instead of "From inside". I want to keep that "From inside" message as is. This suggested change will cause problem with error display code everywhere. :/
You do not have to bind a variable to the exception:
try
{
...
}
catch (Exception)
{
bqBusinessQuery.RollBackTransaction();
throw;
}
Actually, in your case, as you catch any exception, you do not have to even name the exception type:
try
{
...
}
catch
{
bqBusinessQuery.RollBackTransaction();
throw;
}
Or (as suggested #Zohar Peled) throw a new exception, using the caught exception as an inner exception. This way you both preserve the stack and give the exception more context.
try
{
...
}
catch (Exception e)
{
throw new Exception("Transaction failed", e);
}
If you actually want to use the exception for some processing (e.g. log it), but want to rethrow it intact, declare the variable, but use a plain throw:
try
{
...
}
catch (Exception e)
{
Console.WriteLine(e.Message);
throw;
}
catch (Exception)
{
bqBusinessQuery.RollBackTransaction();
throw;
}
If you don't plan on using the exception (e.g. passing the message somewhere) then you don't need to pull it out into a variable. You can simply catch, do custom thing and throw.
I need to change specific system exception message with my custom one.
Is it bad practice to catch an exception and inside the catch block check if the system exception message matches a specific string and if so, throw my custom exception?
try
{
...
}
catch (System.Security.Cryptography.CryptographicException ex)
{
if (ex.Message.Equals("The specified network password is not correct.\r\n", StringComparison.InvariantCultureIgnoreCase))
throw new Exception("Wrong Password");
else
throw ex;
}
Or is there a better way to achieve this.
There's nothing inherently wrong with throwing an exception within a catch statement. However there are a couple of things to bear in mind:
Rethrow the exception using "throw" not "throw ex", otherwise you will loose the stack trace.
From [Creating and Throwing Exceptions] 1.
Do not throw System.Exception, System.SystemException,
System.NullReferenceException, or System.IndexOutOfRangeException
intentionally from your own source code.
If the CrytographicException is really not suitable for you, you could create a specific exception class to represent an invalid password:
try
{
...
}
catch (System.Security.Cryptography.CryptographicException ex)
{
if (ex.Message.Equals("The specified network password is not correct.\r\n",
StringComparison.InvariantCultureIgnoreCase))
throw new InvalidPasswordException("Wrong Password", ex);
else
throw;
}
Note how the original exception is preserved in the new InvalidPasswordException.
To save unwinding the stack when checking the message you could use user-filtered exception handlers - https://learn.microsoft.com/en-us/dotnet/standard/exceptions/using-user-filtered-exception-handlers. This will maintain the stack trace for the unfiltered exceptions.
try
{
// ...
}
catch (System.Security.Cryptography.CryptographicException ex) when (ex.Message.Equals("The specified network password is not correct.\r\n",
StringComparison.InvariantCultureIgnoreCase))
{
throw new InvalidPasswordException("Wrong Password", ex);
}
I want to prevent all exceptions thrown by referenced libraries from escaping my library. I am doing this by filtering all functions through try catch which wraps exceptions if they are not MyException type. The problem that I have is that in my wrap function if the exception is MyException type I end up loosing my original stack trace since I end up re-throwing the same exception from a new place and don't embed the exception that was originally thrown, since the stack trace gets recorded from a new place where exception is re-thrown the stack trace of original throw is lost.
public static Exception Wrap(Exception exception)
{
Exception exceptionToReturn;
if (exception is MyException)
{
exceptionToReturn = exception;
}
else
{
exceptionToReturn = new MyException("Referenced library exception wrapped", exception);
}
return exception;
}
What I am trying to do is to re-throw the same type of exceptions that derived from MyException to keep the original stack trace. However I do not want to check for every child of MyException with code like:
(exception is ChildOfMyException)
exceptionToReturn = new ChildOfMyException(exception.Message, exception);
If I use generics. I cannot specify an explicit constructor.
public static Exception Wrap<TException>(TException exception)
where TException : Exception, new()
{
Exception exc;
if (exception is MyException)
{
exc = new TException();
}
else
{
exc = new MyException("Referenced library exception wrapped", exception);
}
return exc;
}
Is there some way that I am missing or will I have to use reflection to modify _innerException field.
First of all, if your want to rethrow an exception, use:
throw;
and not
throw ex;
The last statement will overwrite your stack trace, the first statement will preserve it.
You can only rethrow an exception inside the catch-block, but not inside anoother method. You could try something like this:
try
{
// Any code
}
catch(MyException ex)
{
throw;
}
catch(Exception ex)
{
throw Wrap(ex);
}
Where your Wrap method only wraps the the exceptions that must be wrapped. In essence it becomes this:
try
{
// Any code
}
catch(MyException ex)
{
throw;
}
catch(Exception ex)
{
throw new MyException("Referenced library exception wrapped", ex);
}
If this does not work for you (because try-catch blocks get repeated over and over), you also could take a look at AOP which might do it for you. Using postsharp, your method could become a bit like:
[ExceptionPolicy(bla bla)]
void MyMethod()
{
// Any code
}
Read more at: http://www.postsharp.net/
If you want to save the original stacktrace and rethrow the original exception you have to throw instead of throw ex. So your wrap function needs to return a boolean which will indicate a throw or rethrow, along with the new exception if there is any.
Something like this:
public static bool Wrap(ref Exception exception) {
if (exception is MyException) {
// false indicates a rethrow of the original exception
return false;
}
exception = new MyException("Referenced library exception wrapped", exception);
return true;
}
// Calling code
try {
// Something
} catch (Exception ex) {
if (SomeClass.Wrap(ref ex))
throw ex;
throw;
}
What is the difference between
try { }
catch
{ throw; }
and
try { }
catch(Exception e)
{ throw e;}
?
And when should I use one or the other?
The constructions
try { ... }
catch () { ... } /* You can even omit the () here */
try { ... }
catch (Exception e) { ... }
are similar in that both will catch every exception thrown inside the try block (and, unless you are simply using this to log the exceptions, should be avoided). Now look at these:
try { ... }
catch ()
{
/* ... */
throw;
}
try { ... }
catch (Exception e)
{
/* ... */
throw;
}
try { ... }
catch (Exception e)
{
/* ... */
throw e;
}
The first and second try-catch blocks are EXACTLY the same thing, they simply rethrow the current exception, and that exception will keep its "source" and the stack trace.
The third try-catch block is different. When it throws the exception, it will change the source and the stack trace, so that it will appear that the exception has been thrown from this method, from that very line throw e on the method containing that try-catch block.
Which one should you use? It really depends on each case.
Let's say you have a Person class with a .Save() method that will persist it into a database. Let's say that your application executes the Person.Save() method somewhere. If your DB refuses to save the Person, then .Save() will throw an exception. Should you use throw or throw e in this case? Well, it depends.
What I prefer is doing:
try {
/* ... */
person.Save();
}
catch(DBException e) {
throw new InvalidPersonException(
"The person has an invalid state and could not be saved!",
e);
}
This should put the DBException as the "Inner Exception" of the newer exception being throw. So when you inspect this InvalidPersonException, the stack trace will contain info back to the Save method (that might be sufficient for you to solve the problem), but you still have access to the original exception if you need it.
As a final remark, when you are expecting an exception, you should really catch that one specific exception, and not a general Exception, ie, if you are expecting an InvalidPersonException you should prefer:
try { ... }
catch (InvalidPersonException e) { ... }
to
try { ... }
catch (Exception e) { ... }
The first preserves the stack trace while the second resets it. This means that if you use the second approach the stack trace of the exception will always start from this method and you will lose the original exception trace which could be disastrous for someone reading exception logs as he will never find out the original cause of the exception.
The second approach might be useful when you want to add additional information to the stack trace but it is used like this:
try
{
// do something
}
catch (Exception ex)
{
throw new Exception("Additional information...", ex);
}
There's a blog post discussing the differences.
You should use
try { }
catch(Exception e)
{ throw }
if you want to do something with the exception before re-throwing it (logging for example). The lonely throw preserves stack trace.
The difference between a parameterless catch and a catch(Exception e) is that you get a reference to the exception. From framework version 2 unmanaged exceptions are wrapped in a managed exception, so the parameterless exception is no longer useful for anything.
The difference between throw; and throw e; is that the first one is used to rethrow exceptions and the second one is used to throw a newly created exception. If you use the second one to rethrow an exception, it will treat it like a new exception and replace all stack information from where it was originally thrown.
So, you shold not use either of the alternatives in the question. You should not use the parameterless catch, and you should use throw; to rethrow an exception.
Also, in most cases you should use a more specific exception class than the base class for all exceptions. You should only catch the exceptions that you anticipate.
try {
...
} catch (IOException e) {
...
throw;
}
If you want to add any information when rethrowing the exception, you create a new exception with the original exception as an inner exception to preservere all information:
try {
...
} catch (IOException e) {
...
throw new ApplicationException("Some informative error message", e);
}
i have a wcf service that does an operation. and in this operation there could be a fault. i have stated that there could be a fault in my service contract.
here is the code below;
public void Foo()
{
try
{
DoSomething(); // throws FaultException<FooFault>
}
catch (FaultException)
{
throw;
}
catch (Exception ex)
{
myProject.Exception.Throw<FooFault>(ex);
}
}
in service contract;
[FaultException(typeof(FooFault))]
void Foo();
when a FaultException was thrown by DoSomething() method while i was running the application, firstly the exception was caught at "catch(Exception ex)" line and breaks in there. then when i pressed f5 again, it does what normally it has to. i wonder why that break exists? and if not could it be problem on publish?
Are you consuming the WCF service from Silverlight? If so, a special configuration is needed to make the service return a HTTP 200 code instead of 500 in case of error. The details are here: http://msdn.microsoft.com/en-us/library/dd470096%28VS.96%29.aspx
Actually your exception is caught but you fail to notice it since visual studio highlights the next line, not the line throwing the exception. Replace
throw;
with some other lines and see them in action.
Take a closer look at catched exception. Was it FaultException< FooFault> or FaultException ? There are 2 version of FaultException class: generic and non-generic
#yapiskan,
C# is a strong typed language Foo< X> != Foo. So if you need to catch some exception, provide exact type in catch clause.
You can learn more on exception handling reading this MSDN article.
The problem is that exceptions are checked in the order they are declared. Try putting the Exception catch block first and you will see that the compiler complains: other catch blocks will NEVER be evaluated. The following code is generally what .Net is doing in your case:
// Begin try
DoSomething(); // throws FaultException<FooFault>
// End try
if (exceptionOccured)
{
if(exception is FaultException) // FE catch block.
{
throw;
// Goto Exit
}
if(exception is Exception) // EX catch block
{
throw new FaultException<FooFault>();
// Goto Exit
}
}
// Exit
As you can see your FaultException never re-enters the try-catch-finally (i.e. try-catch-finally is not recursive in nature).
Try this instead:
try
{
try
{
DoSomething(); // throws FaultException<FooFault>
}
catch (Exception ex)
{
if (ex is FaultException<FooFault>)
throw;
else
myProject.Exception.Throw<FooFault>(ex);
}
}
catch (FaultException)
{
throw;
}
HTH.