Pattern 1 (Parse calls TryParse) — Recommended
| Aspect |
Detail |
| Happy path |
No overhead — TryParse returns true, Parse just returns the value |
| Failure path |
Cheap — returns false, then Parse throws. Exception is constructed once, at the Parse level |
| Exception cost |
Paid only when actually needed |
Pattern 2 (TryParse calls Parse) — Avoid
| Aspect |
Detail |
| Happy path |
Same — no meaningful overhead |
| Failure path |
Expensive — Parse throws an exception, the CLR unwinds the stack, builds a stack trace, then TryParse catches and swallows it |
| Exception cost |
Paid on every failed parse, even though the caller explicitly opted into the "no exception" path via TryParse |
Summary
|
Pattern 1 (recommended) |
Pattern 2 (avoid) |
| Logic lives in |
TryParse |
Parse |
| Failure cost |
One throw at the call site |
throw + stack unwind + catch |
| Exception used as control flow |
No |
Yes |
| Perf in failure scenarios |
Good |
Poor |
| Rule of thumb: Put the real parsing logic in TryParse. Make Parse a one-liner that calls TryParse and throws on false. This matches .NET BCL conventions. |
|
|
Pattern 1 (Parse calls TryParse) — Recommended
Pattern 2 (TryParse calls Parse) — Avoid
Summary