98 lines
2.5 KiB
Plaintext
Raw Permalink Normal View History

== Why is this an issue?
2023-06-14 15:00:43 +02:00
In C#, the https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/statements#13106-the-throw-statement[throw] statement can be used in two different ways:
2021-04-28 16:49:39 +02:00
2023-06-14 15:00:43 +02:00
* by specifying an expression
* without specifying an expression
2023-06-14 15:00:43 +02:00
=== By specifying an expression
In the software development context, an expression is a value or anything that executes and ends up being a value. The expression shall be implicitly convertible to `System.Exception`, and the result of evaluating the expression is converted to `System.Exception` before being thrown.
2021-04-28 16:49:39 +02:00
2022-02-04 17:28:24 +01:00
[source,csharp]
2021-04-28 16:49:39 +02:00
----
try
{
}
2023-06-14 15:00:43 +02:00
catch(Exception exception)
2021-04-28 16:49:39 +02:00
{
2023-06-14 15:00:43 +02:00
// code that uses the exception
throw exception; // The exception stack trace is cleared up to this point.
2021-04-28 16:49:39 +02:00
}
----
2023-06-14 15:00:43 +02:00
In this case, the https://en.wikipedia.org/wiki/Stack_trace[stack trace], will be cleared, losing the list of method calls between the original method that threw the exception and the current method.
=== Without specifying an expression
2023-06-14 15:00:43 +02:00
This syntax is supported only in a `catch` block, in which case, that statement re-throws the exception currently being handled by that `catch` block, preserving the stack trace.
2021-04-28 16:49:39 +02:00
2022-02-04 17:28:24 +01:00
[source,csharp]
2021-04-28 16:49:39 +02:00
----
try
{
}
2023-06-14 15:00:43 +02:00
catch(Exception exception)
2021-04-28 16:49:39 +02:00
{
2023-06-14 15:00:43 +02:00
// code that uses the exception
throw; // The stack trace of the initial exception is preserved.
2021-04-28 16:49:39 +02:00
}
----
2023-06-14 15:00:43 +02:00
=== Exceptions
2023-06-14 15:00:43 +02:00
It is allowed using the thrown `exception` as an argument and wrapping it in another `exception`.
2023-06-14 15:00:43 +02:00
[source,csharp]
----
try
{
}
catch(Exception exception)
{
throw new Exception("Additional information", exception);
}
----
2023-06-14 15:00:43 +02:00
== How to fix it
2023-06-14 15:00:43 +02:00
The recommended way to re-throw an exception is to use the throw statement without including an expression. This ensures that all call stack information is preserved when the exception is propagated to the caller, making debugging easier.
2023-06-14 15:00:43 +02:00
=== Code examples
2023-06-14 15:00:43 +02:00
==== Noncompliant code example
2023-06-14 15:00:43 +02:00
[source,csharp,diff-id=1,diff-type=noncompliant]
----
try
{
}
catch(Exception exception)
{
throw exception;
}
----
2023-06-14 15:00:43 +02:00
==== Compliant solution
2023-06-14 15:00:43 +02:00
[source,csharp,diff-id=1,diff-type=compliant]
----
try
{
}
catch(Exception)
{
throw;
}
----
2023-06-14 15:00:43 +02:00
== Resources
2023-06-14 15:00:43 +02:00
=== Documentation
2023-06-14 15:00:43 +02:00
* https://learn.microsoft.com/en-us/dotnet/api/system.exception#re-throwing-an-exception[Re-throwing an exception]
* https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/statements#13106-the-throw-statement[The throw statement]
* https://en.wikipedia.org/wiki/Stack_trace[stack trace]
2023-06-14 15:00:43 +02:00
include::../rspecator.adoc[]