3 ms·
In the C# stdlib there is at least currently the Task and ValueTask pair, where the latter is a struct optimized for 'failure is rare and success is synchronous
by kevingadd 4y ago
In the C# stdlib there is at least currently the Task and ValueTask pair, where the latter is a struct optimized for 'failure is rare and success is synchronous' that degrades smoothly to the former, which can represent asynchronous computation and lets you recover failure exceptions w/stack without having to ever actually throw. I do wish the async part was decoupled from it, but it's nice that all the error information is preserved if used correctly.
- neonsunset 4y agoWhile correct in terms of convenience, it still wraps an exception with all associated costs. But yet again, you can hand-roll custom `Result<T, E>` even today and implement something like `.Wrap(Func<T> func)` that would produce `Result<T, Exception>` to interoperate. Anyway, if the callee throws an exception, it will be just as costly as any other even if you can examine the `Value/Task<T>` for `.IsFaulted` and `.Exception`. Possibly counterintuitively, if thrown, it will also dwarf the overhead of allocating state machine object and executing `MoveNext()` decoration. Hence even in async there is value to be had in not using exceptions in performance-sensitive scenarios.