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.
We're a place where coders share, stay up-to-date and grow their careers.
We strive for transparency and don't collect excess data.