Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Avoiding Exceptions in .NET isn't some micro-optimization that makes a tiny difference in runtime speed...

Exceptions are pricey pricey things that take time and create some minorly interesting VM/GC behaviour that can impact your application. If at all possible they should be avoided in executed code.

> But it rarely matters how much work you put into something to make it faster. What matters is what you can avoid to do at all.

Using Result<> types to handle error cases is a very good example of doing just that: avoid the big hit of exceptions and poor exception handling in cacadingg situations with sensible return types that let you avoid a buttload of delicate work.



> Exceptions are pricey pricey things that take time and create some minorly interesting VM/GC behaviour that can impact your application.

This is all very vague and handwavey. Not sure about the .NET world but in other systems the costs of exceptions is not significant and they can be used successfully even in the most demanding low-latency applications.

> Using Result<> types to handle error cases is a very good example of doing just tha

Result types don't scale. I suppose it's the sort of thing that programmers have to keep rediscovering for themselves but there's a reason why even Haskell eventually "discovered" exceptions (and I suspect the Rust guys will get there eventually). In the real world where you have lots of deeply nested function calls some of which cross component boundaries good error handling requires three things: contracts (you need to be able to express possible errors at boundaries), context (you need to know exactly what resources have been allocated so they can be cleaned up when an error is caught) and recovery (you need to be able to return the application to well-defined state/point so computation can continue). Frankly, Result types don't give you any of these. What you end up with is a very generic set of errors (necessary to avoid a combinatorial explosion of error types) and a poor-man's implementation of exceptions (see panic/recover in golang). Or I suppose you can write code that doesn't involve deeply nested call-graphs and multiple components and everything is perfectly "flat" and stateless... but this wouldn't be like any real application I've ever seen.


Haskell got exceptions in 1999, I think, but your guess about the motivation as "oh, whoops, result types don't scale" is entirely unfounded.

The real issue is this: figuring out how to do exceptions in a lazy language is simply not obvious. Work was needed, e.g. https://www.microsoft.com/en-us/research/wp-content/uploads/...

Even so, exceptions are generally not used for error handling in Haskell, yet life seems to go on. You'll see code using `throwError` or `catchError`, but usually these will just be providing a nice bit of sugar on top of an Either or Maybe type. So it seems like the takeaway should be that Result types do scale, with proper library+language support.


We sorta use exceptions for IO-based code, mostly because we love parallel combinators in async and they totally require async exceptions to work right.


What I was trying to say somewhere between the lines: Try structuring your code so you don't run into errors in the first place. Because if error handling performance matters, you're having too many of them.


This is always good advice. One should strive so their code doesn't run into errors in the first place.

However, sometimes the errors are actually part of the fabric of the domain itself. They're expected to occur very frequently. The data it encodes is valuable. The way they're handled is important.

Nevertheless, you're right. More often than not, you're better of using traditional exception handling and preventing errors from occurring in the first place.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: