1

I'm wondering if there is any capability to re-throw an existing exception (in a catch clause), within an expression switch case? Please take a look at the code example:

try 
{
    // Some code...
}
catch (Exception ex)
{
  return ex switch
  {
    ExceptionA => // return some value with expression.
    ExceptionB => // return some value with expression
    _ => throw ex
  }

}

The code will end with the following error:

Re-throwing caught exception changes stack information

This code is for example purposes; it's clear that a statement switch case is the obvious solution

switch (ex)
{
  case 1: ...
  case 2: ...
  default: throw;
{
TylerH
  • 20,799
  • 66
  • 75
  • 101
ofir mamo
  • 33
  • 6
  • 5
    Ideally you'd want to change `throw ex` to just `throw`, following [What is the proper way to rethrow an exception in C#?](https://stackoverflow.com/questions/178456/what-is-the-proper-way-to-rethrow-an-exception-in-c). However, the compiler doesn't appear to accept that syntax there. I'd call that an error in either the specification or implementation - not currently sure which – canton7 Jan 11 '22 at 11:09
  • Why is `switch` used in the first place? Why not `catch` different exception types in a normal catch block? Is there some missing code that needs to handle `ex` before switching, eg logging code? – Panagiotis Kanavos Jan 11 '22 at 11:17
  • I agree with your comment, I'll open issue to dotnet to get some more clarifications. Thanks. – ofir mamo Jan 11 '22 at 11:19
  • @PanagiotisKanavos This code is only for example purposes, clearly this is not ideal production code. – ofir mamo Jan 11 '22 at 11:19
  • Looking at [the spec](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-7.0/throw-expression), I think it's clear that `throw ex` is a `throw_expression`, but just `throw` is not (it wasn't mentioned in the Throw expressions spec). Since the arms of a switch expression must be expressions, `throw` is not valid. This is therefore a spec question, and the right place to open a discussion is https://github.com/dotnet/csharplang/discussions – canton7 Jan 11 '22 at 11:20
  • @ofirmamo so what is the *actual* code and *actual* question? Why not use `catch(ExceptionA ex)` ? – Panagiotis Kanavos Jan 11 '22 at 11:21
  • @canton7 I'll ask, thanks. – ofir mamo Jan 11 '22 at 11:23
  • I think the question is "Can you use a rethrow as a throw expression in a switch expression", and the answer appears to be "no" – canton7 Jan 11 '22 at 11:25
  • 1
    Found the proposal: [dotnet/csharplang#1340](https://github.com/dotnet/csharplang/issues/1340). See the discussion there. – canton7 Jan 11 '22 at 11:27
  • 3
    @ofirmamo there may be ways to do whatever you want without requiring `throw` in a switch statement. For example exception filters [can be used for handling as well](https://thomaslevesque.com/2015/06/21/exception-filters-in-c-6/) without affecting the stack. `catch (Exception ex) when (Log(ex, "An error occurred"))` where `Log` always return `false` would log the exception *without* catching it – Panagiotis Kanavos Jan 11 '22 at 11:28

1 Answers1

6

Just catch the specific Exception type:

try
{
    // Some code...
}
catch (ExceptionA exA)
{ 
    // maybe log this
    return "something"; 
}
catch (ExceptionB exB)
{ 
    // maybe log this
    return "something else"; 
}
catch (Exception ex)
{ 
    // log this
    throw; // throw keeps the original stacktrace as opposed to throw ex 
}

As you have asked how to do this with the switch, this should work as well:

try
{
    // Some code...
}
catch (Exception ex)
{
    switch(ex)
    {
        case ExceptionA exA:
            return "something";
        case ExceptionA exA:
            return "something else";
        default:
            throw;
    }
}
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • There's no need to use `catch(Exception ex)` at all, unless the OP wants to do something like logging first. – Panagiotis Kanavos Jan 11 '22 at 11:16
  • Thanks for the reply, however i asked if there is a way to throw existing exception within this specific switch case (which is differ that he expecting expressions, and not statements. – ofir mamo Jan 11 '22 at 11:17
  • @ofirmamo: added the `switch` approach at the bottom of my answer. – Tim Schmelter Jan 11 '22 at 11:21
  • 1
    @ofirmamo why do you want to do that? What's the actual problem to which you think a switch expression is the solution? Why not use different syntax? Eg an exception filter could be used to handle common code – Panagiotis Kanavos Jan 11 '22 at 11:23
  • The only thing I would add is that if there is a need to re-throw the exception, one should **not** simply use throw ex, but rather should use throw new Exception(message, ex) (i.e. using the overload that allows you to include an inner exception). That will preserve the stack information, which was the error noted in the OP. – Pierre Plourde Jan 11 '22 at 15:55
  • @PanagiotisKanavos - I don't want to do that :), however this is an code of my co-team at work, and I used the wisdom of stack overflow guys to establish my comments to them. – ofir mamo Jan 11 '22 at 18:31