The New Option and Result Types of C#

  Рет қаралды 64,212

Nick Chapsas

Nick Chapsas

Күн бұрын

Get our GitHub Actions course and get the Git course for free: dometrain.com/...
Subscribe to my weekly newsletter: nickchapsas.com
Become a Patreon and get special perks: / nickchapsas
Hello, everybody. I'm Nick, and in this video, I will talk about the Result and Option types that C# might be getting in the future when Type Unions eventually release.
Check out the proposal: github.com/dot...
Workshops: bit.ly/nickwor...
Don't forget to comment, like and subscribe :)
Social Media:
Follow me on GitHub: github.com/Elf...
Follow me on Twitter: / nickchapsas
Connect on LinkedIn: / nick-chapsas
Keep coding merch: keepcoding.shop
#csharp #dotnet

Пікірлер: 444
@oussama7132
@oussama7132 Ай бұрын
can't wait to return Task
@stacklysm
@stacklysm Ай бұрын
Aliases are helpful in these situations using Users = ;
@bigice7184
@bigice7184 Ай бұрын
Lol I think people are just going to put that into a new interface to short method signatures back to normal levels.
@_iPilot
@_iPilot Ай бұрын
Empty enumerable is enough instead of Option. Do not return null instead of empty collection. Nick also mentioned that few times.
@cjrada82
@cjrada82 Ай бұрын
Why return an Option? If there are no results, you can just return an empty IEnumerable, and the calling code will handle accordingly by default.
@WDGKuurama
@WDGKuurama Ай бұрын
​@@cjrada82You get a point, A Result monad would give more info (about errors). As an IEnumerable can also be considered as a multi value modad. There is no point to elevate it further.
@alexclark6777
@alexclark6777 Ай бұрын
'bout time C# grew a pair of monads
@asdfxyz_randomname2133
@asdfxyz_randomname2133 Ай бұрын
never realized that monads sounds like gonads...
@aurinator
@aurinator Ай бұрын
Meh, Rust really kicked C# in its Monads IMO... C#/.Net paved the way with async/await, .Net's TPL with asynchronous Tasks, but then Rust comes along and just grabs its developers by those Monads.
@mbpoblet
@mbpoblet Ай бұрын
C# has had monads for a long time... LINQ's built out of them.
@AdrianoKretschmer
@AdrianoKretschmer 22 күн бұрын
lol, I see what you did there...
@mistrzmatik
@mistrzmatik Ай бұрын
Me: Nick, can I use Rust? Nick: We have Rust in C# Rust in C#:
@ochronus
@ochronus Ай бұрын
10/10 meme usage :D
@jongeduard
@jongeduard Ай бұрын
Not a full coincidence. F# and Rust both share a strong OCaml language origin too. And with F# being in the dotnet world, lots of things gradually entered the C# area too.
@GameDevNerd
@GameDevNerd Ай бұрын
// Rust: declares integer called "n" ×&÷>%>×&÷>÷[$*&$
@true_xander
@true_xander Ай бұрын
​@@GameDevNerdlooks very c++ to me
@ranggatohjaya5471
@ranggatohjaya5471 Ай бұрын
let age: i32 = 0; 😊​@@GameDevNerd
@Sayuri998
@Sayuri998 Ай бұрын
All I can say is, I love when features become part of the C# standard rather than a Nuget package. Better visibility, better documentation, guaranteed bug fixes and security fixes. So much good stuff. And I do so agree 100% with everything you said in this video.
@nommet
@nommet Ай бұрын
Guaranteed bug fixes 😆
@user-ci4yb4zl5e
@user-ci4yb4zl5e Ай бұрын
I tottally disagree. We are bloating .NET with pointless features. Bigger dlls, slower performance etc.
@SixOThree
@SixOThree 25 күн бұрын
@@user-ci4yb4zl5e Thankfully you don't need to compile in features you don't use.
@gavinrolls1054
@gavinrolls1054 5 күн бұрын
​@@user-ci4yb4zl5ei don't agree that it results in slower performance
@Crozz22
@Crozz22 Ай бұрын
I'm so happy you emphasize so much the importance of exhaustiveness and forcing yourself to handle all cases.
@joga_bonito_aro
@joga_bonito_aro Ай бұрын
Returning result objects was one of the best things I ever did to my codebase.
@BamYazi
@BamYazi 5 күн бұрын
Exactly the same experience here, been a game changer - started using LanguageExt.Core which also has other Functional style programming stuff - but having to explicitly handle all the result states just made everything in the codebase much cleaner
@Masterrunescapeer
@Masterrunescapeer Ай бұрын
5:15 "Exceptions are incredibly, painfully slow" -> Jon Skeet, "If you ever get to the point where exceptions are significantly hurting your performance, you have problems in terms of your use of exceptions beyond just the performance." Would argue those cases should often just be TryGet or something along those lines if normal logic of possible that does not exist.
@dennisr999
@dennisr999 Ай бұрын
Yes, and then Nick also says "using exceptions like this for flow control is bad practice" ;) I also like TryGet, but it only returns Boolean and not the "reason" for the failure.
@user-ci4yb4zl5e
@user-ci4yb4zl5e Ай бұрын
Result pattern is yet another pointless pattern offering nothing. It is becoming like the american quote about opinions. "... everyone has an pattern". Im tired hear people "exceptions extremly slow bla bla". If youre getting nonstop exceptions then your code has much much bigger problems.
@tarquin161234
@tarquin161234 26 күн бұрын
My understanding of programming is that exceptions are for exceptional events, which does not include validation errors, such as a routing id not being found in a database. This is one of the reasons I always advocate doing more in controller actions rather than pointlessly cutting and pasting everything into a service method, because in the action we have direct access to the http response methods, without needing to awkwardly communicate all those scenarios back from service method.
@projectuber
@projectuber 26 күн бұрын
@@tarquin161234 We just have our repos throw EntityNotFoundException and use middle ware to translate it to a 404. Might not be crazy quick but meets our needs and avoids a bunch of try catch every where. Convention dictates if it will through Get throws Find will not List will not The other option I could do is AOP but I really dont want to explain IL weaving to juniors.
@leerothman2715
@leerothman2715 25 күн бұрын
@@user-ci4yb4zl5eBeing slow isn’t the main problem. People use it to control execution flow which not what exceptions should be used for. Exceptions should used for…well exceptions not expected behaviour. They are just goto statements with glitter.
@patrickkurmann
@patrickkurmann Ай бұрын
I've widely used the C# Functional Extension by Vladimir Khorikov for years, which implemented just that. I am glad it now becoms part of C#.
@alexlo5655
@alexlo5655 Ай бұрын
Me too. This is the great library.
@franciscorusso8062
@franciscorusso8062 Ай бұрын
Me too. Validimir is a rockstar!
@deeplerg7913
@deeplerg7913 Ай бұрын
Nick is gonna milk this proposal for 10 more videos
@nickchapsas
@nickchapsas Ай бұрын
You have no idea
@peculiar-coding-endeavours
@peculiar-coding-endeavours Ай бұрын
As he should
@StephenMoreira
@StephenMoreira Ай бұрын
As he should.
@sohn7767
@sohn7767 Ай бұрын
As he should
@Ruisrd
@Ruisrd Ай бұрын
As he should.
@michaeldileo1954
@michaeldileo1954 Ай бұрын
One tip with LanguageExt options, you can switch on the Case property: Option.Case switch { User u => …, null/_ => … }
@VitalMiguel
@VitalMiguel Ай бұрын
I introduced functional programming in a big company and I must say I really enjoyed working with options result, pattern matching, unions etc. But it takes some time to learn and to read some chaining code when you have a lot of I/O calls. New developers feedback was always this, they enjoy it but they find it hard to understand this new way of thinking. We only had a single bug in production in 3 years that didn't even affect users. It was on cache serialization of a model. Option, Result and enforcing developers to only access the value through pattern matching is the way for no bugs, because 99% of it is when someone forgot to handle a exceptional path on code. We want to achieve that "if it compiles it works" and this helps. I'm also very happy with the introduction of this and see the feedback of devs and next moves.
@2SHARP4UIQ150
@2SHARP4UIQ150 Ай бұрын
I agree. At my company, we fired all the QA teams and replaced them with pattern matching, with no more bugs.
@JollyGiant19
@JollyGiant19 Ай бұрын
@@2SHARP4UIQ150QA and this are both arrows in the quiver of excellence. Why would you fire them??? That’s insane
@LC12345
@LC12345 Ай бұрын
Slowing people down and preventing them from pushing code is a way to reduce bugs too
@2SHARP4UIQ150
@2SHARP4UIQ150 Ай бұрын
@@LC12345 That's a good one, and I will add that another way to eliminate bugs is to fully embrace functional programming and eliminate object-oriented programming. 😉😂
@tauiin
@tauiin 10 күн бұрын
@@2SHARP4UIQ150 the best way to not introduce bugs is simply to not code anything at all, just fire all your programmers and I guarantee you wont run into any new bugs ever again.
@Kotz_en
@Kotz_en Ай бұрын
Result type is great, but I don't really see the how Option would be better than Nullable in modern C# projects, where NRT is enabled (and especially if you have warnings as errors). It's essentially solving the same problem. In projects without NRT however, I do see the benefit.
@chrismantonuk
@chrismantonuk Ай бұрын
I add a Result with Succeeded, Error, Result properties to almost every project I work on, for this very reason. It works well but doesn’t enforce error path handling, so this is a great feature, very welcome. Will save lots of boilerplate.
@joshman1019
@joshman1019 Ай бұрын
I do a lot of automation work, and I grew to love this feature in F#. It is definitely nice knowing you have handled every possible scenario in some way that will never fail.
@WillEhrendreich
@WillEhrendreich Ай бұрын
Love the Fsharp representation, lets go! lets let em know there's more than 12 of us, and that 12 fsharp devs get done what 100 csharp ones can in less time with less bugs.
@joshman1019
@joshman1019 Ай бұрын
@@WillEhrendreich It's a fantastic language! I pair it with C# to get a lot of stuff done, and I couldn't be happier.
@nooftube2541
@nooftube2541 Ай бұрын
“exceptions are slow” meanwhile in production: million exceptions - 1 second one sql request to big table that returns nothing - 1 second yeah… exceptions are problem
@tarquin161234
@tarquin161234 26 күн бұрын
They're probably a consideration in low latency performance critical code, which APIs are often not. Regardless of performance, exceptions are not for normal operating conditions such as validation; they are for halting the flow because of something unexpected .
@weicco
@weicco Ай бұрын
I've written my own Result, Result and Option classes with Monad support. They work like charm. Plus they do away all null ref exceptions since you cannot write "null" anywhere 😂 Next I'm planning to write like virtual machine upon NET virtual (a bit hard to explain) so I can alter the values like in Unity game engine plus with diagnostic support. After that I'm going to write my own programming language, compiler and virtual machine 😂 Edit. Ah, yes. I'm planning to write library so that you can use Monads in Controllers out of the box.
@TehGM
@TehGM Ай бұрын
Exceptions have one benefit: if you use standardized exceptions, you just create a middleware for handling them and suddenly your controllers become really slim, as they should be. The result type, while it's nice we're getting it, will quickly lead to massive bloat in controllers, cause each endpoint suddenly needs to check the result type. Another benefit of exceptions is that unless explicitly handled, it'll terminate the execution of the body at the point of exception - which ensures that application/data doesn't end up in an invalid state. Results pattern shifts that responsibility to the caller, which - depending on the implementation of course - can in theory be error prone. Idk what's the hatred for exceptions. Both result type and exceptions have pros and cons, and both are fine - definitely pick whichever fits your codebase better. I personally am team Exceptions here - the biggest downside is performance, sure - but until benchmarks prove that THIS is the bottleneck IN PRACTICE, then raging at exceptions is just premature optimization.
@Tsunami14
@Tsunami14 Ай бұрын
Exceptions certainly have their place as well I hear ya. But speaking for myself, I follow the motto of "exceptions should only be used for exceptional behavior", and it's always felt a bit icky whenever I've seen/used exceptions as a way to branch the program's core flow. So Option feels like a more natural way to codify that the program should respond differently based on if the object exists. Hope that makes sense.
@ekhm
@ekhm Ай бұрын
@@Tsunami14 How do you define exceptional situation? Trying to update not existing object isn't exceptional situation? It's not a "normal" path.
@nothingisreal6345
@nothingisreal6345 Ай бұрын
On the other hand that "magic" implicit error handling somewhere else in the code reduces readability.
@BlTemplar
@BlTemplar Ай бұрын
Nobody says that Result is easier than Exceptions. Result is a better way to encode errors than Exceptions but it requires some effort! The code looks nicer with exceptions but it's harder to reason about. You see only the happy path and have absolutely no idea what errors can happen and how they can be handled because the handling happens behind the scenes in some implicit weird way. If you introduce a new error in Result, your code will stop compiling because you don't handle the new error. Most of the time it's what you want. With exceptions no matter how many new exceptions you add to the code base, the compiler won't be able to help you with anything. With Result you can map errors to the response directly in the endpoint logic. C# Minimal Apis have very nice TypedResults feature to help you with that. With TypedResults every possible case and the response body ends up in the return type of your endpoint logic. And since it's a type, a lot of things can be infered from it like Swagger schema and other things.
@bh-schmidt
@bh-schmidt Ай бұрын
I'm not sure if I'm team exception, I prefer using a Result type for doing my logic, but I confess that if I'm to use this Result where I have to instance an exception and then put inside an object and returning I will definitely go with the throw method. For me it makes no sense to mix the 2 things, you should use exception or result, not both. Unless you are in a specific scenario of course.
@Sameer.Trivedi
@Sameer.Trivedi Ай бұрын
At this point you C# has enough things to recreate the entire Earth from scratch.
@DaremKurosaki
@DaremKurosaki Ай бұрын
C# is basically that LotR meme of Bilbo going "After all, why not? Why shouldn't I keep it?" to any useful feature in other languages.
@zwatotem
@zwatotem Ай бұрын
It had from C# 2, but now there's 5 ways to do it!
@Sunesen
@Sunesen Ай бұрын
At this point, C# is pretty much turning more and more into F#. :P
@sleeper-cassie
@sleeper-cassie Ай бұрын
The programming language equivalent of carcinisation is that languages keep evolving towards LISP.
@JollyGiant19
@JollyGiant19 Ай бұрын
@@sleeper-cassieLISP’s sin was always the those parentheses
@WillEhrendreich
@WillEhrendreich Ай бұрын
as it should.
@bbqchickenrobot3
@bbqchickenrobot3 27 күн бұрын
Thats a good thing - loved F#. Minus the missing "protected" level access
@gileee
@gileee Ай бұрын
The main issue I have with using Result right now is that I still having to handle exceptions when calling external code (like when I'm calling into ef core to SaveChanges for example) because they throw exceptions on error. If a native Result type is added I hope we'll get versions that return an error result on error which I'll then be able to just return back from my service functions as is. When Java got Optional, in JPA they added, for example "find" functions, which return an Optional as opposed to "get" functions that throw NotFound. Current I have extension methods that wrap a catch over external code calls and return Result.Error(ex). You can handle different exceptions here and return more descriptive Result errors so you don't pollute your code with random exception classes from other peoples code, but it's still a hassle not to be able to propagate directly and handle in one place.
@MightyNicM
@MightyNicM Ай бұрын
Man C# slowly becomes the new C++, it combines every possible paradigm and as a result, gets more and more convoluted.
@evancombs5159
@evancombs5159 Ай бұрын
Yeah, I would like to see Microsoft create a more refined language based on C#, kind of like what Kotlin is to Java.
@yuriy5376
@yuriy5376 Ай бұрын
@@evancombs5159 why not just use C#6-C#7 - when it hadn't yet become a syntactic diabetic.
@EdKolis
@EdKolis Ай бұрын
I thought Kotlin was the love child of a time traveling Java and a future version of C# 😂
@ekhm
@ekhm Ай бұрын
As always when talking about this pattern, only simple examples with 1 lvl nesting. What about nesting methods in methods in methods? If there's a problem on 3rd lvl, how do you transmit result through all levels? Using a lot of bloating code I suppose?
@peculiar-coding-endeavours
@peculiar-coding-endeavours Ай бұрын
For now yes, but that's up to the language designers to fix. In Rust, you can propagate these very simply without always having to check them, and there are libraries to make things very ergonomic. No doubt that people will start doing the same for c#. But I argue that, even if you do need to add some boiler plate, the added explicitness and clarity is worth it.
@BlTemplar
@BlTemplar Ай бұрын
Result and Option are monads. Monads must have map and bind methods. But using these methods directly when combining multiple monads sometimes isn't very nice because of the nesting they introduce. That's why FP languages usually have some kind of syntax sugar for these methods. In Scala it's called for comprehension and I believe in Haskell it's called do notation (not really familiar with it). C# already has this syntax too and it's LINQ. Select is map and SelectMany is bind. LINQ can be used to combine multiple monads together and even asynchnous versions of them like Task. You just have to write generic Select and SelectMany methods so that LINQ can use them.
@damianradinoiu4314
@damianradinoiu4314 Ай бұрын
Not really.. this should be addressed by a proper Bind() method. The purpose of the Monad is to act like a "shell" so it should be pretty easy to change the "shell" because the Invariant (T) remains the same, so it would be just one function call away. I had the exact same problem you say in the past and I solved it like that. Furthermore you can transform it in an extension method and it will simply become something like result.Bind() or something like this
@chris20077777
@chris20077777 Ай бұрын
You mean the developer needs to decide how each function should return a particular result? How horrible!
@evancombs5159
@evancombs5159 Ай бұрын
Try not to nest your methods so much, it results in confusing to follow code. Instead try to create orchestration methods that defines each step in the process, and aggregates the results to produce a new result.
@Artokieffer
@Artokieffer Ай бұрын
It's nice to finally see that Microsoft wants to add Discriminated Unions officially in C#. I found them very neat last year when trying them in Rust for the first time, and I have been very tempted to use them with third-party libraries before, but I never took the plunge. Now that I know it will (hopefully) come in a future C# release, I can't wait to use them. In any case, I think it's a step in the right direction because it will force developers to think ahead in order to handle all possibilities that their program could encounter.
@peculiar-coding-endeavours
@peculiar-coding-endeavours Ай бұрын
I'd recommend taking the plunge anyway, there are some good ones out there, or you can roll your own. I've used it in production for years now.
@caunt.official
@caunt.official Ай бұрын
What will happen to nesting methods? I have a method call tree with depth of 5 methods, each can return multiple errors. So how do I pass the original error up to the caller? Also will caller be forced to handle ~30 possible errors? Or can it just handle all them in once, like catch(Exception) did?
@evancombs5159
@evancombs5159 Ай бұрын
The spec isn't complete in the proposal, but it should be something like this: Result result = doSomething(); if (result.IsFailure) return result.Failure; //Else Continue Processing As well, I would recommend moving away from so much nesting of methods. Instead use an orchestration pattern. It will result in a much easier to understand codebase.
@Hawkeyes1983
@Hawkeyes1983 Ай бұрын
This is perfect timing on this video for me! I am scheduled to give a Tech Talk on this topic next Thursday and had already watched your previous video from a year ago covering the Result Type. Needless to say I'm excited about this feature and have been enjoying using a home rolled version based on your example from the first video. Thanks Nick and keep up the great work!
@bbqchickenrobot3
@bbqchickenrobot3 Ай бұрын
So excited foe the Result and Option - Now if we can get immutable variables by default!
@evancombs5159
@evancombs5159 Ай бұрын
Immutable by default will never happen, too fundamental of a change for it to happen. You'll need a new language.
@jongeduard
@jongeduard Ай бұрын
@@evancombs5159 I have long been thinking about this subject, and my conclusion is that it's related to something much larger. Important difference with a language like Rust is that C# manages certain characteristics of on the level of types instead of individual (local) variables and instances. Examples of such things are are indeed immutability (think about records and readonly structs), but also the distinguishment between value type or a reference type. In Rust it's a lot more obvious to manage all those things on for individual variables and values. You customize mutability, references and ownership all locally based on usage. Remember that C# is a GC managed language while Rust is a low level language like C and C++, and therefore has a stronger orientation on performance, while C# tends to keep more things on simpler to use side.
@evancombs5159
@evancombs5159 Ай бұрын
​@@jongeduard I don't understand what you are trying to say? I've never used Rust so I'm not sure how these things are handled over there.
@jongeduard
@jongeduard Ай бұрын
@@evancombs5159 Ok, no problem. It's just my thoughts on how programming languages evolve differently with different focus. Just intended in addition to what you said, that you would need a different language. I do agree with that.
@LaszloLueck
@LaszloLueck Ай бұрын
Instead of Result you can use Either Type with Right and Left. Handling is same as Result with .Match and so on, but is in my opinion more the correct type for returning a result or the exception.
@user-tk2jy8xr8b
@user-tk2jy8xr8b Ай бұрын
Result type has a built-in "success or error" semantics unlike Either which is just a sum without any additional meaning
@GrzegorzGaezowski
@GrzegorzGaezowski Ай бұрын
I'm probably gonna use Result very seldom. I'm scratching my head how this type became so overhyped where its usefulness is really limited in OO code. I'm especially confused when I hear people say that they replace exceptions with Result (bad idea unless exceptions were used for flow control) or return Result from methods which have side-effects (bad idea because it violates CQS).
@Miggleness
@Miggleness Ай бұрын
Yep. i’d skip this pattern until I have a really good reason to do so.
@ravikumarmistry
@ravikumarmistry Ай бұрын
C# is slowly getting all the features that a functional code need in language itself
@liquidpebbles
@liquidpebbles Ай бұрын
I'm looking forward to it. I'm always fighting with myself, should I return a null here or should I just throw an exception? The constant decision making really saps the productivity out of me. So, if I understand correctly, I'll sort of be forced to handle my cases in a standardized way and won't have to keep making decisions between throwing exceptions or returning nulls.
@Masterrunescapeer
@Masterrunescapeer Ай бұрын
Cool that it's part of C# implementation, still not that much of a fan unless you're planning to handle it one level higher, performance overhead for exceptions are minimal no matter how you argue it as it's an exception. Prefer having a proper stack trace for errors and let the layer that's responsible for it handle it, not permeate layers and layers of Result returns, just obscures code and every single layer you keep having to write stupid if checks. Jon Skeet: "If you ever get to the point where exceptions are significantly hurting your performance, you have problems in terms of your use of exceptions beyond just the performance."
@Raminiya
@Raminiya Ай бұрын
I think this is a very useful addition. It's also very useful to standardize other methods of error returns such as methods that return -1 in case of error for positive integer results or methods that return and array or list and reserve one field for an error. I hope it will also support the case when there is a result and a warning at the same time.
@tridy7893
@tridy7893 Ай бұрын
This may help exceptions have their places of dealing with something that is u n e x p e c t e d, together with eliminating the need for returning nulls/nullable types. IMO, Result looks like a nice temporary fix while we wait for this feature. More elegant and as you said it is nice that it explicitly forces one to handle both outcomes.
@BlTemplar
@BlTemplar Ай бұрын
Compare http calls with db calls. If the db doesn't work, it's usually a catastrophic failure. For example, master goes down and replica for some reason doesn't become available. It's extremely rare situtation which shoudn't happen. But if it does happen one day, Result won't help me here because my whole application will stop working. That's why I don't try catch my db calls and don't wrap them in Result. But I do so with http calls because they are unreliable and fail often. I can gracefully handle failures with Result pattern. I can explicitly fail fast in my logic on bad requests or continue if I get success.
@tridy7893
@tridy7893 Ай бұрын
That depends on the use cases and on the business side, how they allow you to handle a catastrophic failure. Some are ok with retrying later, others need compensation. Then this is a question of timing, in some scenarios, it is not ok to wait for 5 minutes, while others are ok with 30 minutes. For how long code should wait and retry is not up to developers to decide. Another example would be when failed requests stay in a queue and get processed as soon as the DB is back. Anyway, I think it is still a good idea to try-catch, log, and then rethrow.
@lextr3110
@lextr3110 Ай бұрын
I think async Result should automatically map to async Task Option should map to Nullable since its the same.. you should be able to code with option exactly the same as nullable I would prefer if they would reuse tuple and tuple syntax for this.. even for either/or type should be defined similar to a tuple like [string opt, string opt2]? the way they are planing of doing this show the low IQ level involve..
@scottwalker4619
@scottwalker4619 Ай бұрын
I never really understood the “exceptions are bad for controlling flow” argument. If something doesn’t make sense then it is an exception to the logic, when thrown it can be caught and handled explicitly or allowed to bubble up and return in some manner to the user. Returning options of good and bad results just makes me have to handle it directly when in reality if I can’t find a user I want a NotFojndException to bubble up to the user. I don’t want to have to manually return it through the chain
@DisturbedNeo
@DisturbedNeo Ай бұрын
"Will the Option and Result" type also include the monadic behaviors?" "No, C# will not include any monadic behaviors in the language for these types at this time." Sounds like they're going to be difficult to use, even with DUs.
@gliaMe
@gliaMe Ай бұрын
So does an exception has to be passed into the Result object in the invalid case or can it be anything? If it is an exception, it is not actually thrown and thus has no callstack?
@evancombs5159
@evancombs5159 Ай бұрын
You do not use exceptions. Exceptions are for errors in your code or errors outside your control (like losing network connectivity). Instead you would return some kind of error object that details what is wrong with the data being processed.
@jonasbarka
@jonasbarka Ай бұрын
I think these are best for expected errors, like trying to add a duplicate user. No need for a call stack, it only slows things down. If an exceptional error happens, throw an exception. The callstack is useful for fixing a potential bug that caused it.
@nothingisreal6345
@nothingisreal6345 Ай бұрын
Hmm. But: the existing code using exceptions will not profit from this. Why not fix the performance issues of exceptions as well? Also: IMHO readability does decrease. The catch block has a clear well know purpose. In the new Map/Match it is not visible that the second lambda is error handling. You can and should add the parameter name to make it clear which part does what. Also the second part can become "ugly" is case you want to to distinguish for certain error types which is perfectly well defined with exceptions. And: now we again have multiple ways to achieve the same objective, which doubles the learning effort for beginners. Finally: what will happen if one of the underlying APIs throws an exception, e.g. the db.SaveChanges()?. Will that be converted into a Result as well automatically? I guess not. You either have to do it in the routine (not shown in the example!) or you will still have to create a catch block.
@TheKoneko1312
@TheKoneko1312 Ай бұрын
The one thing I REALLY wish for is letting us put multiple errors in a single result. Domain validation could then be handled by tje result type and not needing an external library or custom class.
@evancombs5159
@evancombs5159 Ай бұрын
I think in most cases inheriting from an IError or abstract Error type would be sufficient to switch on any subtype. Unfortunately the proposal does lack a little bit in the details, but that is how I always handle errors when I use a result class. It is how it should work if implemented correctly.
@AJax2012
@AJax2012 Ай бұрын
I'd be curious to see what the performance difference is between this and a library that avoids exceptions all together (like ErrorOr). It looks like you'd still need to create exceptions here but I thought the slowest part of excpetions was generating the stacktrace? Maybe I'm wrong...
@benmuse140
@benmuse140 Ай бұрын
Very much looking forward to this being part of the runtime
@Suriprofz
@Suriprofz 28 күн бұрын
Love either monad, a bit like option and match in rust. Wich still feels cleaner tho
@paramjotsingh4019
@paramjotsingh4019 Ай бұрын
I literally learned and created my own implementation of result pattern 3 days ago...
@aremes
@aremes Ай бұрын
I'm in the middle of "that big rewrite" of a pretty big monolith at the moment. Basically, the legacy code had so many issues in terms of maintainability, testability, etc. so we decided to rewrite it. It's on track for release to customers later this year. We've basically written our own Result and used it all over the .NET Library Code, the HTTP APIs, etc. We're talking _several_ tens of thousands LoCs.. Great timing for that to come out. Not. Whats frustrating is that our implementation is so damn close to that proposal that it wouldnt be that big of a deal to refactor it to use the built in types. But we'd be forcing our .NET library users (Enterprise developers mostly) to then refactor their business layer too. I wonder what other developers that have been using existing Result packages or in-house implementations in their code base are planning on doing now.
@user-sf4ly8yg6v
@user-sf4ly8yg6v Ай бұрын
It's a shame that we don't have the 'static implicit operator Result(Exception e)'
@IcaroFelix2023
@IcaroFelix2023 Ай бұрын
Could you some day make a video about the library C# Functional Extensions ?
@davidbloom7365
@davidbloom7365 Ай бұрын
Does the new Result type render libraries like FluentResult obsolete?
@JeffKwak
@JeffKwak Ай бұрын
Wouldn't `Result` be `Result` instead of `Result`??
@WillEhrendreich
@WillEhrendreich Ай бұрын
You'd think that if you're comparing it to fsharp's one. however, the csharp one seems to be assuming you're using exceptions as errors, so it's implicit. this is ... both frustrating and understandable. I can see wanting the streamlined approach of having exceptions be the way it's handled, but custom error types are very nice in fsharp, because you get the oportunity to use a single Error DU.. *shrug*
@mrwensveen
@mrwensveen Ай бұрын
While you can do Console.WriteLine inside the Match method, I'd return a string (or Option if you want to stay in monad-land) and move the side-effect to the side (a bit): var msg = user.Match(u => $"The name is {u.Name}", "The user did not exist"); Console.WriteLine(msg); It's pretty close to what I'd normally write with nullable: var msg = user is User ? "The name.." : "Y U no exist!?"; Console.etc.
@ProbablePrime
@ProbablePrime Ай бұрын
It seems that the Language-Ext match function and even the switch style that the language would support, could end up re-producing a similar problem to callback hell. Where everything just continually nests, indenting etc. Think of a multi-step operation where multiple things can go wrong based on prior Result/Option objects. Are there features or patterns that can be applied to mitigate that? I think Language-Ext does this with additional functions, that sort of push you down a Functional approach.
@JollyGiant19
@JollyGiant19 Ай бұрын
Result and Option objects are built for functional use so to use them without callback hell does necessitate a functional approach
@user-tk2jy8xr8b
@user-tk2jy8xr8b Ай бұрын
LINQ syntax to the rescue
@ProbablePrime
@ProbablePrime Ай бұрын
@@JollyGiant19 That is fair, I just wondered if there was an approach that didn't use it.
@iliqnikushev3820
@iliqnikushev3820 28 күн бұрын
What i have made in my codebase is a Roslyn Transpiler for the Result. Whenever it finds a method throwing an exception it wraps it in a Result, replacing all throws with the new Result(...), and into a new concrete class, (code stays the same, just wraps the throws) When i create an instance of the UserService, i create it with ServiceCreator.Create() which by default will return a UserService, but if the transpiler picked it up, it will have created a ExceptionWrappedUserService The ServiceCreator.Create is a static class which has a basic Create method and whenever a new type is added, there is now the new Create method Can we just have this in C#'s compilation pipeline and skip the boilerplate? Imho, we should write code as we would normally (with exceptions), and there should be a step before the compiler to manage syntax sugar, if we enable a flag :)
@King21-t7u
@King21-t7u Ай бұрын
Hey Nick thanks for this great one, actually I faced an issue with a null check, will implement this new way of handling these 2 cases, I think the option and result are somewhat similar to how we handle the multiple call-back promises in JS by then and catch I might be completely wrong here.
@JonathanYee
@JonathanYee Ай бұрын
Java's Optional anyone? And Golang return convention? Not a fan of the method calls for this though. It just makes way more indentation in my code but then again I guess its the same as if statement indentation🤷‍♀. But i'd rather use those primitive syntax.
@RomainLagrange1
@RomainLagrange1 Ай бұрын
Hi nick, it would be awesome if we could use the result in a basic if/else statement, because going lambda in a suit of operations will lead to nested lambdas... a pain in the ass to read...
@juliendebache8330
@juliendebache8330 Ай бұрын
The most important part of this is that the option is enumerable, meaning you can use linq on them. So select, firstordefault, etc... This is where the magic happens.
@KasperSOlesen
@KasperSOlesen 23 күн бұрын
Maybe you can add the Switch feature to the option with extensions until its officially implemented? I use extensions quite a bit, but I have not tried adding a switch to something so I am not sure if its possible but I am pretty sure something could be done that would make it nicer looking and explains itself better. The match methods main problem for me is that its not especially obvious that the second option happens when "not matched". The switch would make it cleaner I think while it probably also helps describe the different cases. I agree that its great that it is added. I myself do not enable the "enforce nullable types" in my projects, and I do use nulls a lot, but I also know that I really should avoid nullables and I do often end up having crashes and other strange problems simply because I still use classes, properties and so on that can be null. So when making packages for others to use, I can see why it would help ensure that they run into fewer problems by enforcing this, and also exceptions as a common way of dealing with certain events that you know are common is something I would think best to avoid. As I think you mentioned, exceptions adds a performance hit. If that was not the case I would be less against using exceptions so commonly. But I still use exceptions myself and try catch, and many times its the null properties that cause the exceptions in my code... so... I really should work more on my code ethics.
@valterszaluzinskis2453
@valterszaluzinskis2453 Ай бұрын
result types are realy good, and they opens opportunity to go step further and use railway programming, which allows to write code like it is always on happy path
@Rein______
@Rein______ Ай бұрын
I hope Option will have a .Map function just like the Optional in Java.
@SebGruch
@SebGruch Ай бұрын
Good to see, that things that I'd introduced like 10 years ago, now go into language ;-)
@sacalbal
@sacalbal Ай бұрын
One question : is result (or a variant) serializable ? Because i often use a custom ResultDto to return a result from a web service call, with an error message instead of an exception. It could be interesting to have a standardized result object for this usage.
@Ziplock9000
@Ziplock9000 Ай бұрын
I've always done this myself with my own system rather than using exceptions anyway.
@michalfillo
@michalfillo Ай бұрын
so it is basically the same as ErrorOr?
@drax432
@drax432 25 күн бұрын
Hi, newbie in C#. The Option demonstrated in this video is native part of C# language, or it is only available via third party library? If Option is not part of C#, does microsoft has any plan to include that natively?
@adambickford8720
@adambickford8720 Ай бұрын
If the c# devs are anything like java, this will be met with pitchforks and torches.
@peculiar-coding-endeavours
@peculiar-coding-endeavours Ай бұрын
Luckily, they are not (that's me hoping)
@shadowsir
@shadowsir Ай бұрын
as a previous full-time F# developer, Result was the first thing I added to C# in our codebase.
@peculiar-coding-endeavours
@peculiar-coding-endeavours Ай бұрын
@@shadowsir lol same, I think many people did that over the years, and the number of nuget packages that do this are getting more and more numerous, so I think that triggered Microsoft to think about adding it natively.
@cew182
@cew182 Ай бұрын
Yeah, I've seen a lot of requests for it. So I don't expect the pitches and torchforks
@BlTemplar
@BlTemplar Ай бұрын
It's a very funny comment because Java has had Option for years and has recently added type unions with switch pattern matching as well. You can create Result type and use switch to match over Success or Failure in Java today already. The syntax sucks as usual but Java type unions (called sealed interfaces in docs) are exactly what C# class type unions will be.
@MRender32
@MRender32 Ай бұрын
I can already feel how painfully the Option type is going to interoperate with nullable reference types and Nullable
@andriiyustyk9378
@andriiyustyk9378 Ай бұрын
What about the exception logging? Now if some code base has its own Result class, usually you can't see a stack trace of the error/exception. On a big project, it's a pain, to look for a place where error/exception has occurred.
@petewarner1077
@petewarner1077 18 күн бұрын
It'll be a mistake to use the existing Exception type and its derivatives for the "there was a problem" value of a Result. I get that doing so allows a quicker conversion (return new Exception rather than throw) but I'd rather see a separate Problem type to indicate business logic problems.
@cravecode1742
@cravecode1742 Ай бұрын
Love the Result, not thrilled with Option. Still feels like T?.
@DayMan85Theater
@DayMan85Theater Ай бұрын
What I don't like about this `Result` type is that the non-success case must be an `Exception`, and the idea of returning an `Exception` that was never thrown doesn't feel right to me. I have been using and enjoying the LanguageExt library recently, but I prefer to use `Either` where the "left" type is LanguageExt's `Error` type, which may wrap an `Exception`, or may just represent a "non-exceptional" custom error. Small downside is that I have to explicitly specify `Error` every time, which does result in verbose return types like `Task`. I kind of wish that `Result` would just swap out `Exception` for `Error` as the non-success case.
@ml_serenity
@ml_serenity Ай бұрын
Just a proposal still... But we can hope we get more functional goodness in C#
@aurinator
@aurinator Ай бұрын
AFAIK Rust's Tokio Crate started these Types.
@AkosLukacs42
@AkosLukacs42 Ай бұрын
Maybe a bit earlier. Discriminated unions were in algol back in the 1960's according to Wikipedia Later in ML, ocaml and therefore they are in F# since forever :)
@Miggleness
@Miggleness Ай бұрын
you save the user and find that another user was created with the same email, thereby failing the unique index invariant. boom! you still have to deal with exceptions.
@eliapetrosino1363
@eliapetrosino1363 Ай бұрын
As always Microsoft is cherry picking some already existing stuff (OneOf library for the type Option case and all the managed result types that are already in every company codebase in order to fulfill the lack of error management in C#), placing its watermark on it and claiming to have achieved a great job
@hbjoroy
@hbjoroy Ай бұрын
Hope it will be low level compatible with f#, so that the clr can evolve to much more robust apis, and so that interoo between c# and f# gets easier. Result, option and other DU interop is very tedious today.
@verdurakh
@verdurakh Ай бұрын
Very nice, now I just wish I wasn't stuck working in Framework with strict rules on third party libs I can use
@szikig
@szikig Ай бұрын
How does it differ from this ? OneOf
@dbpieter
@dbpieter Ай бұрын
it doesn't
@alex-bj1il
@alex-bj1il Ай бұрын
Will they migrate the standard library to union types? That seems quite unlikely, considering the amount of code that already depends on exceptions.
@theideaot140
@theideaot140 Ай бұрын
Hey, I hear you like rust so much that we added some into c#, in which you actually work and get paid for. Better still wrap it in try-catch though - it's still c#
@recycledsoldier
@recycledsoldier Ай бұрын
This is a minor nitpick, but I'm not a huge fan of the name "Option" as we use the same word to describe other elements in the code. A lot of static code analysis will also throw errors if you have code that uses a library name like Attribute so I could see this causing issues. Just seems like there could be some nomenclature collision with the options pattern. I would have preferred Optional or HandledResult or something more descriptive.
@jonasbarka
@jonasbarka Ай бұрын
It's an already established name.
@recycledsoldier
@recycledsoldier Ай бұрын
@@jonasbarka I get that. It’s just annoying as there’s possible name collision caused by this. It’s also not super descriptive as to what it’s doing. Generally an option is a configuration
@tomohisatakaoka
@tomohisatakaoka Ай бұрын
We like it , we need this feature in C#
@user-tk2jy8xr8b
@user-tk2jy8xr8b Ай бұрын
Technically those two new types are not going to be monads OOB because they lack Map and Flatten (maybe Pure as well). Extension methods can help with that though.
@CryShana
@CryShana Ай бұрын
Using exceptions in common flows / hot paths for common stuff is incredibly flawed. Not many people realize just how slow they are and their huge negative performance impact when they are being spammed, which is very easily done by a bad actor spamming invalid data at an endpoint. Exceptions are just that, exceptions. They should be used for things that really should NOT happen and you don't expect to happen. So I'm really glad for these new types that will introduce MUCH BETTER error handling - it's the one thing I always loved using in Rust and I'm glad they work similarily as well
@deeplerg7913
@deeplerg7913 Ай бұрын
People have had the "exceptions vs results" debate for years. One of the main problems of result types that I see people mention is that they require a ton of additional code. The people developing C# have to write a good implementation that solves this. And that is beside everything else. It's like the "ORM vs No ORM" debate: for every argument, the other side has two counter-arguments, and vice versa.
@CryShana
@CryShana Ай бұрын
@@deeplerg7913 No, "ORM vs No ORM" debate is orders of magnitude different. With No-ORM you are not just forced to write a TON more code, it's also more error prone and you are (usually) tying yourself to a single database. But with "Results" the only extra code is a SWITCH statement that just replaces TRY/CATCH - it's LESS error prone, not more because it forces the user to handle every possible scenario. But most importantly, this is not an EITHER/OR situation like "ORM or NoORM" --- Exceptions and Results are meant to be used together. Results for common errors, exceptions for... well, exceptions.
@sohn7767
@sohn7767 Ай бұрын
@@deeplerg7913the real problem with that debate is that sides are thinking too pure. Pragmatically, you just use what is more appropriate. Hot loop where you can expect 1000 traverses of the unhappy paths? Result type. You are in a thread and you suddenly lose the connection which only happens due to rare unforeseen events like an outage? Exceptions are the only reasonable choice here.
@CryShana
@CryShana Ай бұрын
@@deeplerg7913 This is not a good comparison. Unlike "ORM vs No ORM" - Results and Exceptions are meant to be used together, Results for common errors, Exceptions for exceptions. Results don't add as much extra code as "No ORM" does - instead they just replace (or extend) the existing TRY/CATCH with a SWITCH or similar. With "No ORM" the development is more error prone because you can easily make mistakes writing everything - with Results you are LESS error prone because you are forced to handle all results. With "No ORM" there is also other downsides like possibly tying yourself to a certain database. But I digress. Results are meant to complement Exceptions, is my point.
@CryShana
@CryShana Ай бұрын
@@sohn7767 @deeplerg7913 Unlike "ORM vs No ORM" - Results and Exceptions are meant to be used together, Results for common errors, Exceptions for exceptions. And they don't require that much additional code either - as long as you're not too extreme with it, they realistically just replace TRY/CATCH
@Mortizul
@Mortizul Ай бұрын
I've been using language-ext since 2017 when I started working for the guy who wrote it. It's a very nice way of coding but once you start working with monadic types, they do propagate throughout your code base and if that's not acceptable to your team, IMO the benefits become limited. I'm excited to see how the C# team implement this in the BCL!
@wizarrc
@wizarrc Ай бұрын
I think that at the runtime level, nullable types and option should be equal if a strict mode is enabled to allow existing libraries to produce option types for consumption without them having to change their api signatures, then with strict mode enabled, do not allow anything null, everything has to be wrapped in option types. Same concept for exceptions with result, only problem is this isn't Java where exceptions are known in the api signature. So if that's the case, first start tracking what kind of exceptions a function/method can throw and then apply this auto-conversation to result type once if opted in and library supports it.
@BlTemplar
@BlTemplar Ай бұрын
The biggest problem with null is that the runtime can’t tell the difference between new Class and new Class for Class. This information is erased at the compile time. Class and Class are on the other hand different and they should be different. Option is a full-fledged type, not some compiler workaround.
@user-tk2jy8xr8b
@user-tk2jy8xr8b Ай бұрын
Nope, having Option is required in some cases. Obviously Nullable and ref types do not support that
@GameDevNerd
@GameDevNerd Ай бұрын
The new Result/Option types I think (at least from my point of view) are being added now to facilitate better code for both AI models and servers/web. C#/.NET is finally becoming a 1st class language for AI development and made huge strides in the past few months, and one area that's a bit problematic for strongly typed languages is all the disparate shapes and types of structs and tensors. It can force you to have to use managed code and reflection and things that aren't optimal for inference performance. The traditional way around that is try to hack together special interfaces with `unmanaged` constraints and use pointers, but that gets rather complicated.
@rcherrycoke7322
@rcherrycoke7322 Ай бұрын
Been waiting for Microsoft to add this to c# - glad it’s finally going to happen
@khealer
@khealer Ай бұрын
Option is good for Database access. You can now represent NONE (missing). Before you only had NULL or NON-NULL. If I understand how it works correctly.
@AhmedMohammed23
@AhmedMohammed23 Ай бұрын
seems like more work for nothing how is that better than throwing the exception (in asp context) and handling any and all of them with the exception handler once instead of handling every case in almost every controller action
@benqbenq
@benqbenq Ай бұрын
13:35 Why do you skip the next question about monadic behaviour? There's no sense in using these types without monadic binding support, because you would need to match every result you get, and it gets worse especially with nested ones.
@Ziplock9000
@Ziplock9000 Ай бұрын
11:28 "Just the happy part" haha
@lollol35
@lollol35 Ай бұрын
So.. We are back to returning error codes and switch statements for all function calls? Perhaps exceptions are slower, but they do make the code a lot easier to read.
@user-fq4qy2my7u
@user-fq4qy2my7u Ай бұрын
Skill issue.
@nickchapsas
@nickchapsas Ай бұрын
How do they do then when I have to look into the entire code base to find where an exception might be caught?
@konstsh2240
@konstsh2240 Ай бұрын
Except that error codes don't type check compared to typed error return path
@peculiar-coding-endeavours
@peculiar-coding-endeavours Ай бұрын
I would say it's the other way around, cause you can have functions calling functions calling functions calling... you get me. And many people do the whole "o well it bubbles up hihi" thing. So if you're working anywhere, you'll have to dig down and up to see where exceptions are thrown and caught. With Results and Options returned from every function, everything is extremely explicit. And that is always superior in my book. Little bit more typing at times, but we're big boys that can type fast enough, and every function becomes very understandable and clear.
@av100ful
@av100ful Ай бұрын
@@nickchapsas Also in web world you have to write exception middle ware. so throwing an error is not bad. you may reduce propagation at one or two places but it will increase code complexity and readability extensively. Not sure this performance worth it?
@EdKolis
@EdKolis Ай бұрын
Java: All this to replicate a fraction of the power of my checked exceptions!
@meirkr
@meirkr Ай бұрын
Is ir possible to switch on the Result same as on the Option?
@sazarkevich
@sazarkevich 13 күн бұрын
I am on project with homegrown Option, Result and it is nightmare... It uses lambdas everywhere, and it is very uncomfortable to understand tens of indentations and nested lambdas. Refactoring cannot be done with tools, only by hands. Usually when I need to understand and modify (more or less significantly) some part of such code - I rewrite it to be more linear, understand logic and do modifications. But possibly Option/Result from video will be is more convenient, as it allow to use switch...
@Sergio_Loureiro
@Sergio_Loureiro 28 күн бұрын
From en.wikipedia.org/wiki/Tony_Hoare: «Speaking at a software conference in 2009, Tony Hoare hyperbolically apologized for "inventing" the null reference: I call it my billion-dollar mistake. It was the invention of the null reference in 1965.»
@kaidouz7756
@kaidouz7756 Ай бұрын
when building my API i came across this problem the returning result from API, the only simple way to handle it was to create a middleware exception to catch thrown exceptions if user doesnt exist or user already exists and so on... (unsucessfull flows), on the middleware exception i would create a object containing the StatusCode and the ErrorMessage and send it. when calling the endpoint i would check if successfull and wrap the response in ApiResponse, containing a property: T? Data if not successfull then i would know that there was error and based on the statuscode from the middleware response i could switch on the code and do whatever i want.
@papamegamind
@papamegamind Ай бұрын
FUCKING FINALLY, after using rust for a few years now I honestly cant stand using non rust like error handling
@peculiar-coding-endeavours
@peculiar-coding-endeavours Ай бұрын
I feel your pain. I'll still keep using Rust though, but at least for the c# projects I wouldn't have to roll out my own Result types anymore.
@papamegamind
@papamegamind Ай бұрын
@@peculiar-coding-endeavours yes agreed
@pedrocunha4322
@pedrocunha4322 Ай бұрын
It would be interesting to check how much performance boost we will have in the dotnet 9
@nothingisreal6345
@nothingisreal6345 Ай бұрын
It will be minimal.
@ErikBongers
@ErikBongers Ай бұрын
There are so many languages out there nowadays, and it seems most of them are adopting the best features of each other. Quite exiting days...although still a bit of a jungle. And I feel bad for C and C++, they served well and deserve our respect.
@cristiz-vf4ww
@cristiz-vf4ww Ай бұрын
How do you chain calls when the function returns Task of something?
@TheRAINMan059
@TheRAINMan059 Ай бұрын
await and use parentheses
"Stop Using Async Await in .NET to Save Threads" | Code Cop #018
14:05
Boolean Is Not Your Friend
12:45
Zoran Horvat
Рет қаралды 40 М.
Running With Bigger And Bigger Feastables
00:17
MrBeast
Рет қаралды 207 МЛН
АЗАРТНИК 4 |СЕЗОН 2 Серия
31:45
Inter Production
Рет қаралды 884 М.
小丑和白天使的比试。#天使 #小丑 #超人不会飞
00:51
超人不会飞
Рет қаралды 37 МЛН
Turns out REST APIs weren't the answer (and that's OK!)
10:38
Dylan Beattie
Рет қаралды 156 М.
How I lost trust in scientists
10:25
Sabine Hossenfelder
Рет қаралды 620 М.
When LINQ Makes You Write Worse .NET Code
9:42
Nick Chapsas
Рет қаралды 31 М.
Exceptions Are Extremely Expensive… Do This Instead
17:15
Milan Jovanović
Рет қаралды 41 М.
the cleanest feature in C that you've probably never heard of
8:13
Low Level Learning
Рет қаралды 135 М.
Brutally honest advice for new .NET Web Developers
7:19
Ed Andersen
Рет қаралды 175 М.
Why Didn't He Get the Job? Let's Find Out! // Code Review
27:25
The Cherno
Рет қаралды 120 М.
Stop Using IEnumerable The Wrong Way in .NET! | Code Cop #019
10:10
.NET and C# are in trouble. Here is what I'd do.
10:57
Ed Andersen
Рет қаралды 58 М.
Running With Bigger And Bigger Feastables
00:17
MrBeast
Рет қаралды 207 МЛН