What’s the Result Type Everyone Is Using in .NET?

2023 ж. 21 Мам.
98 058 Рет қаралды

Check out my courses: dometrain.com
Become a Patreon and get source code access: / nickchapsas
Hello, everybody, I'm Nick, and in this video, I will introduce you to the Result type in .NET. It might not be a native .NET type but it exists in tons of libraries and codebases so in this video I'll help you understand why.
Workshops: bit.ly/nickworkshops
Don't forget to comment, like and subscribe :)
Social Media:
Follow me on GitHub: bit.ly/ChapsasGitHub
Follow me on Twitter: bit.ly/ChapsasTwitter
Connect on LinkedIn: bit.ly/ChapsasLinkedIn
Keep coding merch: keepcoding.shop
#csharp #dotnet

Пікірлер
  • Definitely cover more functional stuff! This kind of content is exactly what we love to see, practical application of functional concepts.

    @EEEdoman@EEEdoman11 ай бұрын
  • I ended up using this concept in C# after working with Rust which has a Result type built in and have found it a great way avoiding throwing exceptions everywhere.

    @nmacw93@nmacw9311 ай бұрын
  • We've been using this for years combined with a railway pattern which makes it more functional. I hated it in the beginning, but has since become my preferred way of coding.

    @SifSehwan@SifSehwan11 ай бұрын
    • The difference is all the pain is upfront instead of spread out over years of production bugs. So really the decision of using the result type is down to whether you reckon you'll still be working on the code in a year or two...

      @orterves@orterves11 ай бұрын
    • Today is the first time I've heard of "railway pattern", why does this make so much sense.

      @local9@local911 ай бұрын
    • Welcome to F# :)

      @dolgan12@dolgan1211 ай бұрын
    • @@dolgan12 While I love this way of writing code, I can't subscribe to any love for F# in it's current form. And that's purely personal rooted in habit.

      @SifSehwan@SifSehwan11 ай бұрын
    • @@orterves This method is error prone if someone fails to check for result.IsError before using it. So you still have the same issues as when someone fails to handle an exception. Which means you still have to wait for exceptions to present themselves in production. So what are you avoiding exactly? The only benefit of this approach is performance (since exceptions in C# are really slow), and more explicit code (which doesn't necessarily make it less error prone, only easier to follow when you're tracking down errors).

      @gileee@gileee25 күн бұрын
  • I've made a general Result type to encompass all general situations. It allows the caller to handle success state and a raised exception. There is also Result and Result in case return values are desired. It's only ~300 lines of code though. There are 3 outcomes: Success, Failure, Exception. It also has implicit operator for convenience.

    @brianviktor8212@brianviktor821211 ай бұрын
  • I'm a big fan of this approach. I used to write similar classes like that years ago when I was working on web forms applications. The Good Old Days 😂

    @CecilPhillip@CecilPhillip11 ай бұрын
  • I've used this sort if pattern for over 10 years and it has never let me down! :)

    @MetalKid007@MetalKid00711 ай бұрын
    • This is probably a better introductory video: kzhead.info/sun/iLdxgatxgGOOimg/bejne.html

      @iuribrindeiro5009@iuribrindeiro500911 ай бұрын
  • I have been using my own ResponseType for a few years now. It has made all of my controller functions 2 lines, one to call the api method that implements the controller and one that transforms the ResponseType into the IHttpActionResult. My implementation is nowhere near as fancy as the one you illustrated. I don't really see the need for any of those extra features, but I am sure they are useful for someone. I did make a change to my ResponseType class after watching the video though. I changed it from a class to a readonly struct. That's a nice improvement.

    @gveresUW@gveresUW10 ай бұрын
  • Known of this approach for years, but with the advent of clean code and driving logic flow through the use of exceptions, it is great to see this being spoken about again, especially in the terms that results are either "It worked" or "It didn't work". We miss that basic premise so much.

    @scottroberts7693@scottroberts769311 ай бұрын
    • Yeh I was using this library in 2016 but now you can't get a job unless you program in the exact way that Uncle Bob says.

      @Mortizul@Mortizul11 ай бұрын
    • @Mortizul but that's a problem in the making. Nothing wrong with convention or best practise, but maintainence, understanding, and reality kick in. It may make things cleaner but does it provide totally clarity, but overall we deal in logic 1s or 0s, true or false Soap box getting off, it also makes the complex seem simpler, but at an expense

      @scottroberts7693@scottroberts769311 ай бұрын
  • I wrote my own Result type using SOLID + functional programming approach in C# back in .NET 4.8 days. Recently I have used that type in one of my commercial projects at work and it works like a charm.

    @mzeeshan@mzeeshan11 ай бұрын
  • I would recommend the C# functional extensions library by Vladimir Khorikov. It has this as well as loads of helper extension methods such as Tap, Bind, Map etc. I love it!

    @umairbutt1355@umairbutt135511 ай бұрын
    • Our team is using it as well

      @Cristian-ek7xy@Cristian-ek7xy11 ай бұрын
  • Have a peek at rust Option and Result for some other useful extensions which are quite simple to implement yourself.

    @twiksify@twiksify10 ай бұрын
  • I remember doing somerthing similar to this years ago with classes that encapsulated the success error, I was under the impression this design pattern was called 'rail-road' programming where you direct the flow of the application based on the result value of the previous call within a stackframe, I added a few extensions allowing the coder to fluently return control to the calling stack frame and depending on the framework bubbled up the result of the call.

    @andyfitz1992@andyfitz199210 ай бұрын
  • I use this pattern myself but it's miles behind of what it can be if C# only had discriminated unions. For example, we wouldn't need an fancy Match or Map or whatever. Just a simple type comparaison in a guard clause and you'd only be left with the "happy path", assuming the language also supported exhaustive type matching (aka the compiler is able to deduce the state the result is in based on context).

    @parlor3115@parlor311511 ай бұрын
  • I've been using a self-made ApiResult class that solved this problem a long time ago. I don't have the implicit operators though; that definitely would make it much easier and more convenient to use.

    @shelbytimbrook2095@shelbytimbrook209511 ай бұрын
    • would u plz share ur ApiResult class?

      @user-gn7bd6mq8n@user-gn7bd6mq8n3 ай бұрын
  • So glad you used LanguageExt ... I hope more demos of this package in the future, so many of its features have been adopted to the language officially.

    @glennstartin8575@glennstartin857511 ай бұрын
  • Yes! More functional discussions, please!!

    @dcuccia@dcuccia11 ай бұрын
  • There is no way you uploded this now, I was looking at your video about (Don't throw exceptions) and I saw Result class and also was watching Amichi Error handling video, and just wanted to understand the Result class more, and now ....... wow Thank you a lot.

    @al-doori2392@al-doori239211 ай бұрын
    • Lol same. I was also watching his same video and actually looking if he had a video on Results.

      @vivekkaushik9508@vivekkaushik950811 ай бұрын
  • I've been using a self-rolled version of this for a while. I don't throw exceptions anymore. I think it would be great to show off the other main benefit to upgrading error state to a first class citizen and using these union types, which is the ability to glue together several operations. Specifically show off the ability to bind, and also the power of map in the result type context and how you can abuse LINQ query syntax with it.

    @DryBones111@DryBones11111 ай бұрын
  • Thanks Nick! I have a rudimentary library following the same basic concept of the Result struct from LanguageExt lib. The one difference I have that they don't is the implicit operator for the failure path as well, and it's SO NICE to be able to return either a new SuccessObject() or a new CustomException(). I also have some ResultExtensions designed to handle IActionResult responses in a similar try/catch fashion. But instead it's more like _methodAsync().HandleSuccess(x => successPath).HandleException(x => failurePath). And you can chain HandleException until finally calling ReturnAsync. I'd be curious on your thoughts Nick!

    @cjamesrohan@cjamesrohan11 ай бұрын
  • I have jumped on this Flow Control as well with the ErrorOr library which is awesome! It supports returning multiple errors as well.

    @DrHeinzDoofenshmirtz@DrHeinzDoofenshmirtz11 ай бұрын
  • interestingly I had that talk with an apprentice some days ago, where talked about the different options to return state and control flow. Turned out to be a quite large topic :-), personally I tend more and more towards Result-Objects, exactly because of the reasons you outlined.

    @michaelrall8142@michaelrall81425 ай бұрын
  • Yes, I'd love a video about functional concepts like Some, None, Unit, etc.

    @user-km7fd2le8f@user-km7fd2le8f11 ай бұрын
  • Language ext is a good and functional library, it's true. But when using such tools, another important story often comes up - serialization. Some libraries have additional extensions (such as JSON serialization), but some others do not. This is an important point, which would also be very useful to highlight. PS. Nick, thank you very much for the useful and very valuable materials and videos that allow you to discover new things and tools, which allows you to be a more effective specialist.

    @anreton@anreton11 ай бұрын
  • Great video, thanks. Look forward to a day where we can use switch expressions with DU deconstruction.

    @dcuccia@dcuccia11 ай бұрын
  • I do love the result approach, specially when coupled with linq syntax to avoid the nasty nesting it usually creates.

    @Aralmo640@Aralmo64011 ай бұрын
  • Lol, I just faced this issue for a service I was calling. The framework could throw (timeout, 404, 500 etc), or the service returns valid or invalid. I invented this very solution to solve it to prevent control of flow problems in my calling code. I like how this uses matching for ensuring callers know what they need to handle.

    @damiantedrow3218@damiantedrow321811 ай бұрын
  • Instead of using Result you better make use of OptionalResult This way we can make dealing with cases for Some, None and Error more declarative and get rid of possible nulls But one of the bad sides of the LanguageExt package is that it blocks the possibility of using NativeAOT nor Ready2Run That happens because this package heavily relies on source generation and it produces blockers for trimming and optimization of the IL code Also, the binary size of this package is massive (about 8 MB) So, if you want to use it in your production project you should take this into consideration Still, very nice approach for discriminated union type and functional style code in C#

    @MrNachosVIDEOS@MrNachosVIDEOS11 ай бұрын
    • But isn't that the purpose of nullable types?

      @neociber24@neociber2411 ай бұрын
    • @@neociber24 True. But nullable type can let you ignore the potential null as an outcome. Nowadays, null can help with interconnection with C APIs and other third party stuff. Also, nullable type handy when you want to optimize internals of your implementation. But in terms of pure C# API it's meaningless and good plant for potential bugs. Same goes for interface: if your interface has a null for specific type as an potential outcome - this is a code smell

      @MrNachosVIDEOS@MrNachosVIDEOS11 ай бұрын
  • It depend on BCL functions or 3rd pary libraires that you are using not throwing exceptions themselves. It ends up you are either creating 3 possible paths (value, exception as value, stack unwrapping exception), or having to wrap everything in try catch blocks. IMO this approach makes sense only in languages where exceptions by value is the only error mechanism.

    @Danny1986il@Danny1986il11 ай бұрын
  • I will def try it in my own projects.

    @Mazzphysics@Mazzphysics11 ай бұрын
  • What I've done is something similar to this. My result type uses an Enum for the status, and an IEnumerable for any messages that I want to return. I then have an extension method in my API project (I tend to use the Clean Architecture pattern, so my result type definition lives in the Application layer) that converts the result type to an IActionResult, depending on the status and data in the result type. It's worked really well so far.

    @jamienordmeyer4345@jamienordmeyer434511 ай бұрын
    • hello, could you please give me the link to the code about this idea (converting object result to IActionResult)

      @hhgforfhuv@hhgforfhuv11 ай бұрын
    • @@hhgforfhuv I don't have a link about this at the moment, but I'll write up a blog post in the next couple days and give you that link. :)

      @jamienordmeyer4345@jamienordmeyer434511 ай бұрын
  • I really like that you pretty much just reimplemented the Rustlang Result enum. Great work!

    @nathancurnow2410@nathancurnow241011 ай бұрын
  • Has anyone else noticed that many of the new features in C# are from functional languages? F# has Result type and you can write result computation expression in few lines and then you do not deal with errors in your code. Of course you'll need to catch exceptions when you'll call code outside of F# and match result with Ok and Error later. F# is a great language!

    @fsharpfan@fsharpfan10 ай бұрын
    • This is not a new phenomenon. Many of C#'s features were inspired by F# equivalents, and often F# was inspired by other ecosystems. async, switch expressions/pattern matching, records, etc. It's a shame more .NET devs don't try F# because there are a slew of important features - and a different way of thinking about programming - that simply cannot ever translate into C#. And, in fact, I'd argue that C# is getting more and more complicated trying to bolt on these things that are not a natural fit due to its inherent design philosophy.

      @AnythingGodamnit@AnythingGodamnit9 ай бұрын
    • @@AnythingGodamnit It's not that new indeed as I've been using delegates/anonymous functions as lambdas since the mid 2000s (I think it was C# 2.0). It was clunky to use back then but I had a FP course at the university and was very eager to use all those slick patterns to solve real problems at work. C# is showing its age and some new features have rough edges or look bolted on indeed (one of the saddest causality is how NRTs are handled - better than nothing though!) but overall, the language doesn't feel all bent out of shape to me and most FP features added over time are really convenient and pleasant to use.

      @fredericbrown8871@fredericbrown88714 ай бұрын
  • Yep, been doing this for a long time. Avoid throwing those exceptions! Though, I would avoid using the word 'Error' or 'Errors'. Usually see a non-passing Validation worded as a 'Breach' or 'Fail'. Also, need enough data stored so can send down the standard format for 400's.

    @timschwallie1589@timschwallie158911 ай бұрын
  • Also you can use Try...(out result) patter. You can also add out failure to signature if you need.

    @nooftube2541@nooftube254111 ай бұрын
  • What about when the error happens somewhere deep inside the codebase? E.g. class A uses class B, which uses C, which uses D. If an error happens in class D, then you need to handle it in all classes C, B, and A, right? And what if class D has many methods with many possible errors, then you also need to handle all of them in all other classes? With traditional exceptions you could just throw an exception in class D and catch it in class A. Then, if it's an exception you expect (e.g. validation error) you can properly handle it and show validation errors to the user. Otherwise you just return generic 500 server error response. That seems much simpler, even if not as robust as using Result type. So I really don't understand how Result type could make your code better in a huge codebase.

    @mindaugasw@mindaugasw11 ай бұрын
    • Agreed.

      @user-fu6mp6et8p@user-fu6mp6et8p8 ай бұрын
    • Exactly. Argument against throwing exceptions is “exceptions are expensive” and argument against Result types is “there is a lot of checking”. I personally prefer throwing exceptions because I can just throw exceptions and be done with it.

      @softcodeacademy@softcodeacademyАй бұрын
  • I like the pattern because provides a consistency to a common problem and cleaner code, but it adds some debugging and readability overhead that I would like to see an improvement on.

    @saffronomicon@saffronomicon7 ай бұрын
  • I'm writing my bachelor work about Minimal API (it was heavily inspired by you, Nick!), and in my work I used this approach via ardalis/Result. It's quite a useful library, I love it, you can even translate your result to minimal API response. It has less of control, but it's simple. Perhaps, I'll write my own implementation because I want to return conventional results for scenarios like 400, 404 etc.

    @winchester2581@winchester258111 ай бұрын
    • 😳 sorry but how can you write thesis about minimal api, what is scientific about it? It’s just way of organizing you endpoint, who cares if it’s based on mvc , or any other concept, it’s point is to allow hit you http server and get desired resource based on ‘path’(http request) Back to the video, This concept of result monads is only a way of flow control that language like rust, functional supports and c# tries to mimic. It’s great but it’s will hard to add native support because all standard libraries should have been rewritten to not throw the exception but rather expose it as a monad, and some api would also has to change. Basically even string parse would need to be rewrites to plainly admit that hey you can get an string or errorX and when you get error do something with it, or at least panic ;) it’s embarrassing that so many people are overwhelmed and treat it like a genius revolution, but it shows how advanced programmers are these days 😢😂 And of course I would love to have it in c# and I am trying to adopt it as much as I can in my application code. Maybe eventually even some libraries starts to be based on that idea and c# devs teams figure somehow how to add support with maintaining the backward compatibility 🎉😃

      @brtk7@brtk711 ай бұрын
    • @@brtk7 well, we don't have overwhelming requirements for our workaround, so I picked this topic for some sort of experiments. Yes, you can say that it's just a technique for API structuring, but as Nick mentioned it can give you the possibility to build a new approach So it can be something that simple. Other people in our university literally picked up topics like Spring Boot WebFlux or just CRUD applications

      @winchester2581@winchester258111 ай бұрын
    • @@winchester2581 you could instead build your own custom middleware on top on asp and invent, research new way of building api, that would have better way of defining these endpoints or even get rid of asp and incorporate simple http library or use standard code primitives like httpListener. And that would add value to your project and present you more like a researcher rather than a technical noob getting existing with technology that doesn’t completely understand. Sorry for that, but If I were to appreciate such projects, I would insult people who truly strive and put effort into their thesis work. 🥲😁

      @brtk7@brtk711 ай бұрын
  • Man, I just got used to working with OneOf library, and now you come up with this :D

    @tarikpalic6304@tarikpalic630411 ай бұрын
  • 5:16 "I'm gonna link them in the description below" - you forgot :(

    @HartzFEAR444@HartzFEAR44411 ай бұрын
  • Great video. I would only add that this is not a `concept in C#` but a concept in most current languages (especially ones with union types), and is a concept in development and monads as a whole. C# is missing it, and it's up to developers to crudely create it in C#. I know it's mentioned later, but missing Union types and monads is a sore point for me with C# It's important for developers to look outside of their eco-system and know what is missing or neat in other ecosystems. Or even better know what doesn't exist outside your ecosystem, and why your ecosystem is 'better' for a given task/solution.

    @crazyst3ve01@crazyst3ve0111 ай бұрын
    • Yep! It is wildly used in functional languages, and as Mads Torgersen said: "OO is kind of screwed... it was not designed for the cloud". -> kzhead.info/sun/drCEipuSnoifl6c/bejne.html

      @iuribrindeiro5009@iuribrindeiro500911 ай бұрын
    • @@iuribrindeiro5009 DO you know that there is something called industry standard languages and growing languages? And toy languages?

      @obinnaokafor6252@obinnaokafor625211 ай бұрын
    • @@obinnaokafor6252 I'm not sure what do you mean by "toy languages" but I think I do understand related to the other 2. Functional is not a language but a paradigm created on early 30s, if that is where u are going with. Don't get mad, I'm just replicating what the C# lead designer said :)

      @iuribrindeiro5009@iuribrindeiro500911 ай бұрын
  • Been using Result for 5+ years. I can't live without it.

    @MrSaydo17@MrSaydo1711 ай бұрын
  • Brilliant, thanks!

    @ershadnozari@ershadnozari11 ай бұрын
  • Could you please make a video about this pattern in F# vs C#? Just to people know what we are looking for in C# by using this.

    @iuribrindeiro5009@iuribrindeiro500911 ай бұрын
    • He does not use f#

      @obinnaokafor6252@obinnaokafor625211 ай бұрын
  • Looks like it's functional programming stuff. Too bad I don't know it yet but it seems to be very powerful. Good video as usual.

    @AnonymousDeveloper1@AnonymousDeveloper111 ай бұрын
  • did you guys notice where this leads to? I been playing with the same concept of a Result type such that programmer cannot access the value directly, only call Match(onSucessDelegate, onFailureDelegate), but then this quickly turned all my code into a function calling another function calling another function passing the result of each operation to the next! I am starting to see the concept of functional programming but man this is totally outside comfort zone!

    @mhDuke@mhDuke5 ай бұрын
  • > can only be one of the two values Partially true, there are Success and Faulted states. However, default(Result) will have State=Faulted and throw "bottom exception" on accessing the Exception prop. This approach is similar to what they have there in Either, but Either has the "Bottom" state explicitly (I won't stop arguing that the "bottom" state makes no sense in an eager language and it's a poor translation from Haskell). Actually you can see IsBottom in the intellisense list at 9:32

    @user-tk2jy8xr8b@user-tk2jy8xr8b11 ай бұрын
  • Great video nick! We've been using this approach lately but the implicit operator part really blow my mind. Also would be good to see a video of the Language Extention package👌👌

    @rafaeldericksanchezlockwar4920@rafaeldericksanchezlockwar492011 ай бұрын
  • I'm using it with ROP (Railway) and I love it. I'm currently trying to create "fluent ROP" that supports async operations - which is not easy... I would love for you to take a crack at it. Would be interesting to see. For instance : var result = await someOperation(parameter).OnSuccess(x => x...).OnFailure(x => x...);

    @TheCarstenSuurland@TheCarstenSuurland11 ай бұрын
  • I wish this would make it to the BCL instead of having to import e.g. LanguageExt. C#8's nullability already is a great Optional compatibility option out of the box. Judging by how functional C# is getting, this is probably just a matter of time before we have functional constructs in the BCL.

    @allinvanguard@allinvanguard11 ай бұрын
    • Option is not the same as nullable. You can wrap it, but it is different.

      @crazyst3ve01@crazyst3ve0111 ай бұрын
    • @@crazyst3ve01 Sure, it's not the same, but the semantics are similar enough for most use cases

      @allinvanguard@allinvanguard11 ай бұрын
  • Am very interested in Maybe and Either like used in Language Extns, although have found it hard to convince others, would be good to raise the knowledge of these basic functional approaches.

    @fishzebra@fishzebra11 ай бұрын
  • Personally, I prefer to throw custom exception that could be catched later on in the code. Having result type making lots of methods looking cumbersome and given that generics makes your redability worse with the time, one can also privilege just simple .net exceptions

    @Kantragor@Kantragor9 ай бұрын
  • I tried to implement my own Result and Option types based on Beef lang's version which is based on its enum type. Works pretty much the same as in Rust - but C#-ish. The problem obviously is that C# doesn't have the feature yet. The code gets more verbose. And in my implementation there is a problem with the generic arguments not being inferred.

    @marna_li@marna_li11 ай бұрын
  • Aye I’ve helped create an enterprise system from the ground up using LanguageExt. It’s a bit rubbish switching between that and OO or procedural so stick with a pattern if it suits your case

    @MrBleachFix@MrBleachFix11 ай бұрын
  • I wish c# had value-holding enums like rust does. Rusts Result enum that holds Ok(value) and Err(error), aswell as the similar option some/none are super useful, and Result is a super commonly used thing there (because it has no exceptions in the language)

    @_Aarius_@_Aarius_11 ай бұрын
  • I have always prefered the action's return type match to match the model. This enables ApiExplorer to produce documentation to match the method definition instead of having to annotate with ProducesResponseType which just feels like redundant boilerplate that is also open to error. Does anyone know a solution to this or are we just forced to return IActionResult when using result objects?

    @peterriesz69@peterriesz699 ай бұрын
  • Nick in the end you mention to link the fluent result package. but its not in the description.

    @xanhxanh5097@xanhxanh50978 ай бұрын
  • please make more videos on functional programing principes in c#

    @nikamamniashvili8633@nikamamniashvili863311 ай бұрын
  • I find myself using this very often in C# ever since I started learning Rust. Go figure.

    @Ankh.of.Gaming@Ankh.of.Gaming11 ай бұрын
  • In my project we use a custom result type with the flag Is success , and Result = object target but I will propose the library that you success to avoid have the lots of if, thanks

    @luiscamacho1917@luiscamacho19179 ай бұрын
  • I've been using a (inferior) result type similar to this for ages... Didn't realise it was a common thing tbh. Funny how people end up at similar destinations with things like this... I remember many years ago my astonishment that ORM's were a thing, having been struggling with my own implementation hah.

    @pingu2k4@pingu2k411 ай бұрын
  • Based on the prototype, the ValidateAsync method does some IO like networking, otherwise it wouldn't be async. With your FP shenanigans, you now have 3 possible outcomes: success, validation error, or exception due to failed IO. This means you have to handle 3 cases otherwise you'll introduce bugs. For this reason, I usually throw exceptions for validation errors. They simplify code at call sites, also improves readability. In the rare cases when performance cost of exceptions matters, I usually do something like `bool tryDoSomething(out R result);`

    @soonts@soonts9 ай бұрын
  • What was always bugging me about this approach was lack of discriminated unions in C# which force you to create some artificial interfaces (or separate class + additional code for one type to another) just to be able to return multiple types of failures (e.g. method is calling two other methods which return different types of failures). Not only such interface is artificial, it also binds two different parts of code in a way that might be distant from each other in your codebase. Of course, someone can argue that exceptions actually all derive from one class so you can do the same with failures, but that's a stretch to my taste.

    @proosee@proosee11 ай бұрын
  • Used this approach for years. Away with throwing exceptions and ending up in nondeterministic control flows. The little bit of added verbosity is a small price to pay for cleaner and predictable flow.

    @peculiar-coding-endeavours@peculiar-coding-endeavours11 ай бұрын
  • This approach reminds me of a OneOf package that you've used in one of your videos, which in my opinion is more flexible. Using OneOf, you can specify multiple positive results, multiple errors and match all of them, so that you don't just return BadRequest when there is an error. Instead you can use more appropriate status codes for each error type. Do you think Result type has any advantages over it?

    @uladzimirmalhin2379@uladzimirmalhin237911 ай бұрын
    • if you use for error something like rust enums you don't need extra parameters

      @adrian_franczak@adrian_franczak11 ай бұрын
    • I started using OneOf after Nick showed it in a video a couple months back. I was wondering why would you use a Result class instead of OneOf. It seems like OneOf would be more flexible.

      @alex22932@alex2293211 ай бұрын
  • I think it is important not to use abbreviations in lambda when using those new concepts. I am pretty familiar with the result / either type but I always name the lambda param when matching with full name. I think "movie" instead of "m" might help people understand: "ah ok that is where I can access my value". Of course people can see the type of the lambda param but still I think making it easier for new people is never bad :)

    @gaxkiller@gaxkillerАй бұрын
  • Looking forward for the LanguageExt video.

    @OrgesKreka@OrgesKreka11 ай бұрын
  • Looks developers of this lib didn't have enough letters... otherway I can't explain how they decided to name method "IfSucc" ...

    @nooftube2541@nooftube254111 ай бұрын
    • If it succs then it is okay 😅

      @ryan-heath@ryan-heath11 ай бұрын
  • The Result type in langauge-ext says /// `Result` (and `OptionalResult`) is purely there to represent a concrete result value of a invoked lazy operation /// (like `Try`). You're not really meant to consume it directly. Any comment on the "You're not really meant to consume it directly." part?

    @raphaelbatel@raphaelbatel11 ай бұрын
  • In the context of a web Api, When would you not wrap an exception in a result? Would it just be when you dont want to share the error details with the user as it's not something that could help them? Eg an IOException or something like that

    @andrewstevens7764@andrewstevens776411 ай бұрын
  • Suppose I tried to create a movie that is already in the database what should the movie service do? Is the movie validator responsible for checking if the movie already exists? I would think the movie validator is purely the movie itself such as title can't be more than 50 characters. Now the movie year is also tricky because it relies on another "time" service should that really be in the movie validator? What do you think of adding another validator that handles time requirements? As well as a movie validator for the repository? Where would you draw the line? Does each dependency on a service deserve its own movie validator? Maybe I need a movie validator factory which will build a composite of movie validators depending on how much I want to validate. For the create case I would want to validate static properties like the movie title, time based properties like the year, and uniqueness properties like the Id. What do you think?

    @crazyfox55@crazyfox5511 ай бұрын
  • First time I've seen the PureAttribute - can you go into detail on that?

    @scott98390@scott9839011 ай бұрын
  • Hey @NickChapsas what do you think about always returning same object for every API, something like Response object which has properties data, errors, code,..., and if code has failed it will return this object whit errors property inserted or if it is sussecful it will return data property inserted, what do you think about handling in this way? And I saw you used exception throwing as way of validation, isn't maybe this way too expensive for validation of data?

    @dejansavanovic4476@dejansavanovic447611 ай бұрын
  • if i'm not mistaken, it is the rust way to return error or result

    @user-nw7jo5xw9x@user-nw7jo5xw9x11 ай бұрын
  • 5:19 where are those vids you talked about exception flow control

    @TheNorthRemember@TheNorthRemember4 ай бұрын
  • I'm making my own Result type with a roslyn analyzer that would enforce error checking, I think it's the next step on this game (it is also a struct so no heap allocations for results are needed)

    @diadetediotedio6918@diadetediotedio691811 ай бұрын
    • I'm working on exactly the same 😂 very interesting to dive into the roslyn analyzers

      @BillieJoe512@BillieJoe51211 ай бұрын
    • ​@@BillieJoe512 It's very fun (not every time hahahahaha) to work with them, I kinda like the whole roslyn thing. If they made roslyn source generators to be able to modify the source code I would do something like function inlines for those .Match functions over result types, but until this occurs I work with the available tools

      @diadetediotedio6918@diadetediotedio691811 ай бұрын
  • I still think we need some kind of global try/catch setup, because exceptions are like uninvited guests-they can show up anywhere. Predicting every single place an app might throw an error just isn't doable. So, it makes me wonder, why go through the hassle of wrapping everything in a Result and making our codebase heftier? Here's a scenario: suppose you have a method that's been smooth sailing, no exceptions, so you didn't wrap it in a Result. But then, during development, something changes, and now it might throw an error. This means potentially updating a lot of code that calls this method, even when there might not be a strong reason for it. Typically, a standard approach with middleware could handle this situation without forcing any major changes elsewhere. Seeing as we're already using Task, adding more wrappers into the mix feels like we're going overboard. If we keep this up, our type definitions are going to get so bloated, not even a UWQHD screen could display them all. 🙂

    @user-fr7nn1yq3m@user-fr7nn1yq3mАй бұрын
  • And now use IPipelineBehaviour to return a ValidationFailed, if validation fails, next() otherwise. I gave up on that and moved the Validation into my IResultHandler, which is suboptimal, so say the least

    @hanspetervollhorst1@hanspetervollhorst111 ай бұрын
  • I have a project that uses exceptions for control flow and have been thinking about porting it to use this Results approach, but i have one issue with this: The MovieService is triggering validation and checking. I dont think i want to have that code in every single service. Normally with exceptions you have something that triggers that automatically, so i'm wondering how something like mediator (the pattern) behaviors could be used to automate this and how that code would look like.

    @user-vk5ww8wd8b@user-vk5ww8wd8b5 ай бұрын
  • If they ever stabilize the new enum types this will be even better

    @neociber24@neociber2411 ай бұрын
  • if you add a "public object Value => IsSuccess ? _value : _error" would allow you to use native switch expression, res.Value switch { TValue v => do your thing, TError e => do your other thing } In addition, LanguageExt is a bit old and doesn't work well with AOT compilation and stuff like that, be careful

    @nocgod@nocgod11 ай бұрын
    • True, but you'll probably lose a lot of performance with the boxing. If that's not important in your use case, then by all means, go for it.

      @RobinHood70@RobinHood7011 ай бұрын
    • @@RobinHood70 not a lot in most cases. Plus usually it used for classes, so everything already boxed.

      @nooftube2541@nooftube254111 ай бұрын
    • @@RobinHood70 you might pay some price. Easily testable with benchmarkDotNet:)

      @nocgod@nocgod11 ай бұрын
  • This seems like an interesting approach. I'm just a bit concerned that valuable stack trace information may get lost when handling errors this way?

    @notarobot22@notarobot2211 ай бұрын
  • Which approach do you generally prefer when comparing this Result type approach to something like the OneOf library that you demonstrated in the "How to use Discriminated Unions Today in C#" video from a few months back?

    @JexsGG@JexsGG11 ай бұрын
    • I use both. I use OneOf generally and I have a result type through oneof

      @nickchapsas@nickchapsas11 ай бұрын
  • How do you think exception handling from external resources should be? for example mongo driver/sql/external sdk clients and HttpClient they all use the exceptions patter. Should I Try-Catch all outer resources in a wrapper class that returns Result?

    @ethanshoham2855@ethanshoham285511 ай бұрын
    • Interesting question. A lot of SDKs do use exceptions for things like 404, 409 and 429.

      @PelFox@PelFox11 ай бұрын
  • It reminds me a structure of an Observable from rxjs with two callbacks.

    @IcaroFelix2023@IcaroFelix202311 ай бұрын
  • Did the same thing actually by using objectresult class . the happy path was returning the actual object . the error path was the objectresult with the error and the code inside . same things

    @user-qi7mk6be7u@user-qi7mk6be7uАй бұрын
  • it will be nice to make more videos on LangugeExt:)

    @vencislavvidov@vencislavvidov11 ай бұрын
  • Hi Nick, What is the different from the package OneOf ?

    @guybahar6856@guybahar685611 ай бұрын
  • If you're at all confused just remember - a monad is just a monoid in the category of endofunctors. What's the problem? (*Please* can C# get sum types as a core feature. They've already stolen pretty much everything else good from F#. Though currying and computation expressions would sure be nice too...)

    @orterves@orterves11 ай бұрын
  • The big mistake people make about this pattern is that they view the result type as either success or an error. When it is really returning an accept type or an out-of-band message that halts normal execution. Viewing it like that you can use it for more use cases and make the return very simple. Also, using monads makes it nicer. But most people have a hard time grokking that so at work I go with simple rather than easy (for me).

    @dovh49@dovh4911 ай бұрын
  • Yes. I would like to wrap my head around functional.

    @ronosmo@ronosmo11 ай бұрын
  • What if your repository throws an exception? It looks like it would bubble up to your controller which no longer has a try/catch?

    @mtsmithtube@mtsmithtube11 ай бұрын
  • I am a big fan of result types, but not of the Match(), IfSuccess(), etc methods. I don't like that they implement the same behaviour as the native language constructs without using them. this can be confusing to junior programmers and I imagine it does not pair well with code flow analysis and other tools. I'm trying to write roslyn analyzers to force - or remind - the dev to check a result's state before using its value (as does @DiadeTedio Tedio)

    @BillieJoe512@BillieJoe51211 ай бұрын
  • Gotta love seeing concepts from languages like Rust make their way into C#

    @Matt23488@Matt234889 ай бұрын
  • Really nice video

    @R0ckyRocket@R0ckyRocket11 ай бұрын
  • Any more information about LanguageExt is always welcome.

    @TheTortillaCurtain@TheTortillaCurtain11 ай бұрын
  • if there possibilty multile error then how should hangle in Api Controller?

    @user-ft8bd7tx3e@user-ft8bd7tx3e2 ай бұрын
  • Glad to see people advocating for this pattern but this is why I moved to Rust!

    @ianknowles@ianknowles11 ай бұрын
  • While I do really like this idea and I have experimented with it on and off several times, something makes me skittish about propagating its usage everywhere. This may be an incorrect and unfair comparison (correct me if wrong). but when I have used it, I have found it needs to be used from lowest layer all the way back to the controller consistently, as you would an async/await Task pattern. But using it all the way from data layer back to controller, I cannot see avoiding the use of many captures, which does worry me about using it too much through the code-base. While some may argue that the same can happen with LINQ lambdas, usually your LINQ lambdas are not extraordinarily complex, just simple predicates/mapping methods. The logic you need inside of some of these functional lambdas can get quite complex and lead to captures. Of course, I could have just been using this wrong all along, and I hate to ever say a pattern is bad when it has a such a cool potential, but I guess for whatever reason I can't be sold 100%.... yet. And then I have to also wonder why the C# committee hasn't ever adopted this officially even though it's been around for a while now. It does make me wonder if there are some things that don't work with the language constructs 100% without some side-effects.

    @ChristopherWodarczyk-hg6jm@ChristopherWodarczyk-hg6jm8 ай бұрын
  • It’s like async when you start using it you will almost always need to alter the call chain as well, or you will shallow errors. That’s said, I only see value in this when doing validation and (sometimes) calling an external component. In other case just let the exceptions flow to the upper level.

    @ryan-heath@ryan-heath11 ай бұрын
  • This was a spooky one. Terror everywhere

    @slowjocrow6451@slowjocrow64516 ай бұрын
KZhead