Re-throw an exception in a conditional expression - c#

What is the correct way of rewriting the code in the following catch block using a conditional expression? if supported!?
try
{
return await _client.GetStreamAsync(_uri);
}
catch
{
if (IsConnected)
throw;
else
throw new IOException();
}
C# compiler does not like the following
IsConnected ? throw : new IOException();
Note that re-throwing a caught exception, like the following, is in violation of CA2200
try
{
return await _client.GetStreamAsync(_uri);
}
catch (Exception ex)
{
throw IsConnected ? throw ex : new IOException();
}

Your first example is fine. throw; will rethrow the exception leaving the stack trace in tact. As an alternative, I would suggest just conditionally catching the exception when IsConnected == false:
catch when (IsConnected)
{
throw new IOException();
}
You can read more about the when keyword in the docs.

Related

How to catch a rethrown exception?

I have the following code:
try
{
await _policyService.QueuePayment();
}
catch (Exception ex)
{
var slackError = new ErrorNotificationMessage("{ex.Message}");
await Notify(slackError);
}
I want to give more detail and log it to Slack if the Exception is a Security Exception, so I extended this try/catch block as follows:
try
{
await _policyService.QueuePayment();
}
catch (SecurityException ex)
{
throw new Exception("detailed message", ex);
}
catch (Exception ex)
{
var slackError = new ErrorNotificationMessage("{ex.Message}");
await Notify(slackError);
}
However this does not catch the rethrown Exception and log it to Slack. What am I missing here?
As it was already mentioned in comments by #canton7, you'd need a try-catch inside the catch (SecurityException ex) in order to catch it. However, as it was also mentioned, that doesn't make sense here. It's also not a common (or rather, correct) practice to wrap an exception just to change the error message.
Just use standard boolean logic:
try
{
await _policyService.QueuePayment();
}
catch (Exception ex)
{
var message = ex is SecurityException ? "Some very important message" : ex.Message;
var slackError = new ErrorNotificationMessage(message);
await Notify(slackError);
}
However this does not catch the rethrown Exception and log it to Slack. What am I missing here?
When we throw an exception explicitly it can be catched at the caller end by enclosing the method call in a try catch block. We cannot throw and catch the exception from a catch block in same method unless we add another try catch which does not actually make sense here.
What you should be doing is directly throwing that exception like :
try
{
await _policyService.QueuePayment();
}
catch (Exception ex)
{
if(ex is SecurityException)
{
// for security exception do something different
}
else
{
var slackError = new ErrorNotificationMessage("{ex.Message}");
await Notify(slackError);
}
}

Throwing Exceptions Correctly

I have the following code
public HttpResponseMessage AddDataToDatabase([FromBody] Data data)
{
try
{
var token = _tokenService.GetToken(Request.Headers.Authorization);
if (_pService.Permission(_tokenService.GetUserId(token), "Enable_Data"))
{
_noteService.AddData(data, _tokenService.GetUserId(token));
return Request.CreateResponse(HttpStatusCode.OK, "Data has been added to the case.");
}
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.Forbidden, "Cannot add data because you don't have permission."));
}
catch (Exception exception)
{
if (exception is SqlException)
{
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, exception));
}
if (exception is ArgumentException)
{
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.Conflict, exception.Message));
}
throw;
}
}
I want to catch the Forbidden Exception like other exception in the catch block but not sure how to do that. The way I am returning Forbidden exception right now breaks unit tests which return SqlException and ArgumentExpception.
How can I throw exceptions correctly?
By far, the easiest way is to simply do it like this.
catch (Exception exception)
{
throw;
}
Unlike your code, this code also handles unanticipated exceptions instead of just SqlException and ArgumentException.
But why are you doing this? If you want the exception to propagate out to the caller, then simply remove the try...catch block in this method. Then just throw the desired exception in your code.
If you are capturing and converting third-party exceptions, the recommended approach is as follows.
catch (SqlException exception)
{
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, exception));
}
catch (ArgumentException exception)
{
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.Conflict, exception.Message));
}
you should probably replace your if logic in your catch by using more selective catch :
catch (SqlException exception)
{
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, exception));
}
catch (ArgumentException exception)
{
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.Conflict, exception.Message));
}
The uncaught exceptions will simplypass through (as when you you use throw;).
If you want to catch another type of exception, just add it to the list.
However, it is not very clear how your tests are broken. You should provide more details at this level if you want more help.

Custom exception- Try catch - in c#

it is allowed to use custom exception, where the exception can be thrown like below.
try
{
int foo = int.Parse(token);
}
catch (FormatException ex)
{
//Assuming you added this constructor
throw new ParserException(
$"Failed to read {token} as number.",
FileName,
LineNumber,
ex);
}
But in a normal try catch block, it says , throwing exceptions will clear the stacktrace.
try
{
ForthCall();
}
catch (Exception ex)
{
throw ex;
}
So in custom exception,how it managed to use throw exception, without clear the stacktrace?
There are several ways this can be done.
As mentioned in this link In C#, how can I rethrow InnerException without losing stack trace?, you can use the ExceptionDispatchInfo Class
with code similar to
try
{
task.Wait();
}
catch(AggregateException ex)
{
ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
}
Another way is to have your handler return a boolean, whether the exception was handled or not, so you can use this in your catch clause:
catch (Exception ex) {
if (!HandleException(ex)) {
throw;
}
}
where HandleException is your custom Exception handler. Gotten from this link: How to throw exception without resetting stack trace?
Whenever you use throw with an exception object, it fills in the stack trace at that point. (Compare to Java, which populates stack traces when an exception is constructed.)
If you use throw without an exception object, which you can only do in a catch clause, the caught exception object is re-throw without alteration.

Reuse catch for all catches

is it possible to do something like the following:
I want to catch a custom exception and do something with it - easy: try {...} catch (CustomException) {...}
But then i want to run the code used in the "catch all" block still run some other code which is relevant to all catch blocks...
try
{
throw new CustomException("An exception.");
}
catch (CustomException ex)
{
// this runs for my custom exception
throw;
}
catch
{
// This runs for all exceptions - including those caught by the CustomException catch
}
or do i have to put whatever i want to do in all exception cases (finally is not an option because i want it only to run for the exceptions) into a separate method/nest the whole try/catch in another (euch)...?
I generally do something along the lines of
try
{
throw new CustomException("An exception.");
}
catch (Exception ex)
{
if (ex is CustomException)
{
// Do whatever
}
// Do whatever else
}
You need to use two try blocks:
try
{
try
{
throw new ArgumentException();
}
catch (ArgumentException ex)
{
Console.WriteLine("This is a custom exception");
throw;
}
}
catch (Exception e)
{
Console.WriteLine("This is for all exceptions, "+
"including those caught and re-thrown above");
}
Just do the overall catch and check to see if the exception is that type:
try
{
throw new CustomException("An exception.");
}
catch (Exception ex)
{
if (ex is CustomException)
{
// Custom handling
}
// Overall handling
}
Alternately, have a method for overall exception handling that both call:
try
{
throw new CustomException("An exception.");
}
catch (CustomException ex)
{
// Custom handling here
HandleGeneralException(ex);
}
catch (Exception ex)
{
HandleGeneralException(ex);
}
No, it doesn't do this way, you either catch a specific exception (linearly) or a generalisation. If you wish to run something for all exceptions you would need to keep a record of whether or not an exception has been thrown, perhaps what it was etc, and use finally, or another contrived, probably more 'messy' and verbose, mechanism.

WPF Dispatcher Thread- Using lambda expression and throw to dispatch exception to UI thread

try
{
string s = null;
s.PadLeft(10);
}
catch (Exception ex)
{
// send exception to UI Thread so it can be handled by our global exception
// handler
Application.Current.Dispatcher.Invoke(DispatcherPriority.Send,
new Action<Exception>(e => { throw ex; }), ex);
}
As you can see, 'throw ex' will truncate the stacktrace, I would like to use throw instead of throw ex but I get:
A throw statement with no arguments is not allowed outside of a catch clause.
How can I use lambda expression to throw the exception without truncating stacktrace?
Why don't you just create a new Exception with the old exception as InnerException?
e => throw new WhateverException("your message", ex);
That preserves the original stacktrace.

Categories

Resources