C# throw vs throw ex: preserving stack traces and designing exception handling

C# Language Interview Q&A November 13, 2026 csharp

Exception filters (when) for selective catching.

csharp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// ======================================================================
// Q: throw vs throw ex? How do you design exception handling?
//
// - Exception filters (when) for selective catching. Only catch what you can
//   handle.
// - No exceptions for expected flow (e.g. "not found"). Use null, TryXxx or the
//   Result pattern there.
// - Custom exceptions for business rules (DomainException) and one central
//   IExceptionHandler that converts them to ProblemDetails (Q6).
// ======================================================================

try { await erp.SendOrderAsync(order, ct); }
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.ServiceUnavailable)
{
    logger.LogWarning(ex, "ERP unavailable for {OrderId}", order.Id);
    throw;          // ✓ keeps the original stack trace
    // throw ex;    // ✗ the stack trace starts here: you lose where the error happened
}