You got it wrong (about exception handling and flow control). The way you use Result is correct and when you can do that instead of throwing exceptions - you should go for it. Exception handling is much slower and it's not meant to replace the normal workflow. The whole idea of throwing exceptions is, that you may have several method calls nested (even recursively) and you may handle the exceptions way up in the stack calls. If you do this using Result - the whole process turns into a lot of result checking and returning errors back to the caller, which is obviously worse and makes the code hard to read just like it's harder to read when you use exceptions as flow control.
Things get a lot better when you can use Railway Oriented Programming but C# isn't built for it. There is certainly a trade-off: explicit function contracts or nicer nesting. At this point in my career I choose the former and then lean toward languages that support both (F#).
Ah functional programming... you know what they say - it's like communism - most arguments against communism can be applied to functional programming as well:
If it is so good, why does it fail every single time?
Why is it preached only amongst scientists, who didn't work a real job a single day in their life?
If you believe it's so good, why don't you make your own company and use it to take over the market?
When it fails the explanation was: it's because it wasn't pure functional programming...
You got it wrong (about exception handling and flow control). The way you use Result is correct and when you can do that instead of throwing exceptions - you should go for it. Exception handling is much slower and it's not meant to replace the normal workflow. The whole idea of throwing exceptions is, that you may have several method calls nested (even recursively) and you may handle the exceptions way up in the stack calls. If you do this using Result - the whole process turns into a lot of result checking and returning errors back to the caller, which is obviously worse and makes the code hard to read just like it's harder to read when you use exceptions as flow control.
That's a great point I hadn't considered.
Things get a lot better when you can use Railway Oriented Programming but C# isn't built for it. There is certainly a trade-off: explicit function contracts or nicer nesting. At this point in my career I choose the former and then lean toward languages that support both (F#).
Ah functional programming... you know what they say - it's like communism - most arguments against communism can be applied to functional programming as well:
You seem like a nice person.
This is an understatement :)