top | item 22226157

(no title)

ProstetnicJeltz | 6 years ago

We tried to use a result type in C# for cases like this. For example, we want to save an object, returning the updated object (on success), or an error on failure.

Unfortunately in static languages this leads to an unholy amount of boilerplate:

public Result<SomethingGood, SomethingBad> PerformUpdate(int goodThingId, UpdateForm form) { ... return new Result<SomethingGood, SomethingBad>(error); ... return new Result<SomethingGood, SomethingBad>(obj); }

The type annotations were hell. Sometimes there were three cases we wanted to consider. We went back to using exceptions, and are keeping a keen eye on the new C# features.

So ultimately - I agree with the author that throwing exceptions is fine, when things actually go wrong. It's also not that bad when things kinda went wrong, but sometimes the effort required to fix it isn't worth it.

discuss

order

UK-Al05|6 years ago

Frankly, that's because C# doesn't support proper discriminated unions in a concise way.

F# is a lot better at using result types. You don't even need to specify the return type.

lllr_finger|6 years ago

It's been awhile since I've been in C#, but in other static languages like Rust and Kotlin with type inference, it would look more like:

public Result<SomethingGood, SomethingBad> PerformUpdate(int goodThingId, UpdateForm form) { ... return Err(error); ... return Ok(obj); }

which is considerably less boilerplate-y. When there are three cases you want to consider, that's no longer a sum type consisting of just success or failure - that's a different sum type. Maybe even represented as Result<ThreeCases, Error>.