C# throw vs throw ex: preserving stack traces and designing exception handling
Exception filters (when) for selective catching.
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 } |