A different way to return data in C# with OneOf

Sdílet
Vložit
  • čas přidán 17. 08. 2020
  • Become a Patreon and get source code access: / nickchapsas
    Check out my courses: dometrain.com
    Hello everybody I'm Nick and in this video I wanna talk about a package called OneOf. This library provides F# style discriminated unions for C#, using a custom type OneOf. An instance of this type holds a single value, which is one of the types in its generic argument list. It might not be my personal favourite way of doing things but I think it is a good project and I want to give it some exposure because I can definitely see some people benefiting from it.
    Give OneOf a star: github.com/mcintyre321/OneOf
    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
    #dotnet #csharp #oneof

Komentáře • 109

  • @CarmenSantiNova
    @CarmenSantiNova Před 3 lety +15

    It's an interesting idea but I have to say that exceptions has one BIG benefit and that is that it can bubble through code, you don't have to specify what bubbles.
    This gives you the opportunity to have any layer of your application return an error. Normally in a service-oriented architecture you would have multiple layers where a problem can occur.
    If you were to be explicit with every error that can occur down below you would end up with a very large combined list of results at the top. I am of course not saying that your shouldn't catch and handle exceptions but rather let them bubble but in our case we have introduced what we call a ValidationException which is used to transport validation errors from different services in a normalized manner.
    Although I really like the explicitness of states it takes me back to the Java world where you would define which exceptions a method could throw.

  • @sombraSoft
    @sombraSoft Před 3 lety +27

    This is absolutely genius. In this example it's way better than XML doc for "throws exception"
    It enforces you to aknowledge what kind of returns you can have and handle them accordingly.
    This pattern matching thing reminds me so much of Elixir (but this is even better, it's STRONGLY TYPED). Also, the names you're giving to these "exceptions" like InvalidEmail are totally like atoms in elixir or symbols in ruby.
    GOOD JOB!

  • @xMrMiagix
    @xMrMiagix Před 3 lety +13

    Alright. Let's do some refactoring of APIs today :D

  • @lahcencodery
    @lahcencodery Před 3 lety +2

    I really this way of handling results! I am going to give it a try

  • @TheJessejunior
    @TheJessejunior Před 3 lety +1

    maaann!! thema subjects your´re abording are always so helpfoul! thanks a lot

  • @MartinvanZ
    @MartinvanZ Před 3 lety +1

    Interesting. I Just implemented this pattern in my mobile app. For my synchronization I return a result object. I Used an enumeration as the result status and extra fields to return optional objects. I Like it better than throwing an exception. In my case I use a case statement to handle the result.
    This approach is nice because you can clearly see the results possible per function. In my case I would have to create different enumerations per function.
    The only downside I can think of is that when you would have many possible results it may clutter the function definition. More of a readability issue.

  • @jyrikgauldurson8169
    @jyrikgauldurson8169 Před 3 lety +1

    I have used a similar implementation of the Either monad for these cases coming from a functional background. I usually combine errors into one so I have two types, the correct one, and the error route. In the theory, this is known as a disjoint union or coproduct.

  • @zc2012
    @zc2012 Před 3 lety +14

    the OneOf approach looks a good as it clearly shows what the client can expect from a service, but also increase the complexity of the client code. I personally like the Result approach.

    • @nickchapsas
      @nickchapsas  Před 3 lety +7

      The problem with the Result approach in my opinion is that when you start having more Exceptions that you need to handle in there then you need to edit that Failed clause which means that your code is violating the open-close principle. It's also using a beefy Exception object which allocates more memory.

    • @tdp4276
      @tdp4276 Před 3 lety +6

      @@nickchapsas Agreed on violation of the open-close principle, that's annoying. But to get around the use of "heavy" exception objects, just don't use them, make your own objects to encapsulate in Result and interpret those instead.

    • @lextr3110
      @lextr3110 Před 3 lety +1

      one problem with Wrappers is the constant need to Wrap and Unwrap.. it obscurate the type interfaces

    • @SebGruch
      @SebGruch Před 3 lety +1

      @@nickchapsas Therefore, for my project I'd created dedicated ProcessingResult, not hauling Exception, but only ErrorCode enum and ErrorMessage. But I have a very strict situation, where I have only 3 error codes (actually these are like BadData, Ignore, TryLater, with the message providing more details on the error - either validation error or caught exception message) and do not expect it to expand.

  • @mrshk_vv
    @mrshk_vv Před 3 lety +2

    Nice guide. I wasn’t know it and I hope will be implement that feature in my next projects. Hello from russian viewers)

  • @jackkendall6420
    @jackkendall6420 Před 3 lety +6

    I love the trend of C# slowly becoming more and more of a functional language :)

    • @vasilybulochkin4622
      @vasilybulochkin4622 Před 3 lety

      It would be really cool if C# will become Object first just like F# is function first)

  • @seancpp
    @seancpp Před 2 lety

    I really like this. Thanks for showing it

  • @whattheduck7125
    @whattheduck7125 Před 3 lety

    So many years, still learning

  • @carlosjunior5371
    @carlosjunior5371 Před 3 lety +2

    This approach makes the code much more expressive. Although I prefer to use domain notifications. Thanks for sharing!

    • @adriangodoy4610
      @adriangodoy4610 Před 2 lety

      why it makes it much more expensive?

    • @Alguem387
      @Alguem387 Před 2 lety

      does it tho? its just wrapping it on a struct

  • @dastrn
    @dastrn Před 3 lety +2

    This is really good stuff.

  • @davidopdebeeck8953
    @davidopdebeeck8953 Před 3 lety +1

    it’s neat, might use it but it’s still very painful compared to doing the same in F# code. thanks for the video, great stuff as always.

  • @sunnypatel1045
    @sunnypatel1045 Před 3 lety +2

    Hi nick love your vids ! Could you do a vid on automapper custom value resolvers please

  • @cristerramirez8522
    @cristerramirez8522 Před 3 lety +1

    Nice tutorial!

  • @Spartan322
    @Spartan322 Před 3 lety

    Yeah, I've made my own Variant classes before, its convenient when you can't or don't want to manage the individual types and know you're always going to return just one thing.

  • @alirezanet
    @alirezanet Před 3 lety

    Cool library

  • @olayemiafolabi2151
    @olayemiafolabi2151 Před 3 lety +2

    Thanks for the tutorial. Would like to see your approach to achieve returning error message without throwing exceptions. Also, looking forward to a short explanation on when to use struct vs class

  • @viktorasmickunas2527
    @viktorasmickunas2527 Před 3 lety

    Very interesing, thanks

  • @8ytan
    @8ytan Před 3 lety

    OneOf seems like it would become very impractical for APIs which are capable of returning a larger variety of responses to a single request. It looks neat and tidy when there's three possibilities, but what about when there's 10? In my opinion, Result also suffers from this to some extent.

  • @justinharris6197
    @justinharris6197 Před 2 lety +1

    I would have went with OneOf as a type of Result that allows you to return something other than an exception, though I assume this was just to demonstrate that you can return more than 2 values.

  • @mariuszskuza2425
    @mariuszskuza2425 Před 2 lety +1

    I prefer to create a basic class and then another extended class that inherit the basic one, for example: Response (base) and Response.Success (data) or Response.Error (status code, message) and then the service returns Response type of any kind.

  • @VennYT
    @VennYT Před 3 lety

    So cool!

  • @johnolawale2749
    @johnolawale2749 Před 3 lety +1

    This approach doesn’t look bad at all.

  • @alfredoquintanalopez2265
    @alfredoquintanalopez2265 Před 3 lety +1

    Great Video Nick!!! What about the performance of OneOf, no the exception path, but the normal path? In the Exception path, performance should be better, because the exception really never throws. Thanks, your videos are amazings!!!

    • @nickchapsas
      @nickchapsas  Před 3 lety +3

      OneOf performance wise is better than all three of the approaches I showcased. The first one is obviously the slowest due to the exception throwing and the middleware invocation. The OneOf is only the fastest, over the Result one because OneOf is using structs which will allocate less and faster memory compared to Result's exception objects.

    • @mycollegeshirt
      @mycollegeshirt Před 2 lety

      @@nickchapsas that's why I thought I wanted to use these with my structs, so I can still have polymorphism without losing speed by using interfaces or .

  • @ernstgreiner5927
    @ernstgreiner5927 Před 3 lety +2

    Thank you for the tutorial!
    AFAIK there are plans to support 'Discriminated Unions' in future versions of C#, so there should be more IntelliSense support too.
    I'm learning F# since a couple of weeks and what i can say is that one way of F# is handling this is like:
    Result
    where TResult is the happy path where you expect one result and TError the error path where DU are used.
    It's a very descriptive way of handling processes, i like this very much!
    But anyway, thumbs up to OneOf

    • @nickchapsas
      @nickchapsas  Před 3 lety

      I cover the Result approach in this video. It's the second example I give

    • @ernstgreiner5927
      @ernstgreiner5927 Před 3 lety

      @Nick Chapsas
      what i'm talking about is, the signature of the method in the third example
      public OneOf CreateUser(User user)
      will change to
      public Result CreateUser(UnvalidatedUser user)

    • @nickchapsas
      @nickchapsas  Před 3 lety

      @@ernstgreiner5927 Oh I see. Well I don't really see the reason for this one. I will introduce unnecessary nesting and you can't really extract the "Fault" part without repeating yourself since two responses are not the same.

    • @ernstgreiner5927
      @ernstgreiner5927 Před 3 lety

      This is a functional thing, from an OOP pov you wouldn't get such ideas.
      In F# it's used for process chaining like
      let completedOrder = unvalidatedOrder |> validateOrder |> assembleOrder |> shipOrder |> chargeOrder |> closeOrder
      every step returns on success an distinct type, ValidatedOrder, AssembledOrder, ShippedOrder...
      In C# there will be one OrderObject with an status enum, in F# 10 types...

  • @lextr3110
    @lextr3110 Před 3 lety

    you can also return a tuple of (T, exception) and pattern match on it.. or object inherithance is actually a discriminated union.. pattern matching on T is the same... its only the simple way to create these discriminated union in some languages that give them these advantage
    they can very easily become class hiearchy at any time from the discriminated union..

  • @JustinBaur136
    @JustinBaur136 Před 3 lety

    This is super cool, I think I sort of like the exception way more though. I use it with custom exceptions so that I can escape at any level and have a handled structured response. I also don't need to wrap everything in a try/catch because I can have non custom exceptions pass back a 500 and let me know what the exception was or just hide it depending on the environment.

    • @nickchapsas
      @nickchapsas  Před 3 lety +2

      The main problem with the exception one is that it is adding a lot of "magic" and it lets you assume quite a lot about the behaviour. It also introduces a 10-30 ms which would be an absolute no-no if you're interested in writing high performing applications.

    • @JustinBaur136
      @JustinBaur136 Před 3 lety

      @@nickchapsas Yeah absolutely. I've normally had to write API's that are highly traceable at the cost of a few ms. So I normally have some middleware to track request information so I might as well have that middleware catch exceptions for me. I can't agree more on middleware feeling like magic though. I wish there was a more structured way to build it.

  • @IvanBerezhnyk
    @IvanBerezhnyk Před 2 lety

    Hi Nick, thanks for the video. I wonder what in this case would be your cup of tea ? :) How to separate API and Application layers properly?

  • @donka86
    @donka86 Před 2 lety

    I have two minds about c# implementing more and more functional patterns not just as packages but at the language level too. For example I love scala as a multi paradigm language, but if you work in a team with mixed dev background (f / oo), people always tend to fallback to what they know best and enforcing practices becomes hard. One could argue, you have C# and F# and they are both interoperable on the CLR. Why not modularize your app and use the right language for the right part of the app.

  • @mishamovdivar
    @mishamovdivar Před 3 lety

    The only thing that concerns me is nesting. What if you have to call another method (which also returns AnyOf) within the one of the Match lambda, and call another method within that method, etc. It'll make a code really hard to read.

  • @sheveksmath702
    @sheveksmath702 Před 2 lety

    I love discriminated unions in F#, but definitely agree that this is pretty verbose in C#. I wonder if you could use C# 8 switch expressions & enums to get something sort of close to this? Obviously it wouldn't be the same, but might be fine for a lot of cases.

  • @hanspetervollhorst1
    @hanspetervollhorst1 Před rokem

    You really got me curious on this and I started using it. Now, I wonder, when combining it with MediatR ( IPipelineBehaviour ), is there a way to know in the Handler-method, that our TResult is of type OneOf, so we instead of throwing Exceptions from there, we can ie return a Microsoft.AspNetCore.Mvc.ProblemDetails ?

  • @benjamincharlton3774
    @benjamincharlton3774 Před 3 lety +1

    Really interesting video, thank you! So, if throwing exceptions from the service layer to the controllers is not a good way to communicate common validation problems, and using OneOf is also not your cup of tea, what is your favourite way to do it?

    • @nickchapsas
      @nickchapsas  Před 3 lety +2

      As of late I’ve been actually using OneOf quite a bit more but I am bouncing back and forth between OneOf and Result from Language.Ext

    • @benjamincharlton3774
      @benjamincharlton3774 Před 3 lety

      @@nickchapsas Nick, sorry to bother you again. I am trying to put together what you have taught me about OneOf, CQRS and EventSourcing. Do you return OneOf from a write-side CommandHandler such as: public class CancelBookingCommandHandler : IRequestHandler

  • @filipecotrimmelo7714
    @filipecotrimmelo7714 Před 3 lety

    Nice! =)

  • @Stanniemania
    @Stanniemania Před 3 lety +1

    What if you were to swap the user exists and email invalid type parameters in the future? It looks like the caller will not break if you do that so it will start returning the wrong ActionResults and nobody will know (unit tests should catch it but still).

  • @teseract7442
    @teseract7442 Před 3 lety

    how to create badRequestt for a list of badRequest, more fields?

  • @evidgamer1699
    @evidgamer1699 Před 2 lety

    This pattern is natively built into Rust. Some of the concepts of Rust are very advanced and surely should be adopted in C# also.

  • @DanteDeRuwe
    @DanteDeRuwe Před 3 lety +2

    Something in me says that this could have been done differently. Some kind of combination with Option should exist where you can get the value, check if it's null, or get any other "Error" struct by implementing a base class, so that you would not have to put OneOf.
    Something like OneOf< Option, UserErrorBase> could work, but that's not elegant.
    You have any idea if this has been done before, or if either LanguageExt or OneOf supports this? Also, is this a good idea or does it have some obvious flaws?

    • @sombraSoft
      @sombraSoft Před 3 lety

      You could use a base class. But then you'd lose the point of actually seeing the name of the different types it returns.
      For example if a given API returns OneOf and 25 different classes derive from UserErrorBase, how would you know which cases do handle? You'd certainly not try to pattern match all possibilities.

  • @nikbrons9786
    @nikbrons9786 Před 3 lety

    For Web Application, the best practice for (email) validation is to use fluentvalidation (you can take out simple validation from domain services).
    It seems to me that the OneOf approach is not justified enough if you only need to return or . IMHO, no need to return more different exceptions in one place to handle them (using OneOf or not)
    How often have you encountered handling various exceptions (greater than 2) on your controller?

    • @nickchapsas
      @nickchapsas  Před 3 lety +1

      Firstly there is no single best practice for such topic in my opinion. There are layers and you get to choose where to do what. OneOf doesn’t focus on exceptions but rather alternative paths. They can be both parts and bad Paths. I actually have at least 3 different types of responses in most of my controllers and oneof is a lifesaver there

  • @eddyhanderson6916
    @eddyhanderson6916 Před 2 lety

    I would like to know how throwing exceptions can bring perfomance issue.

  • @WarrenLeggatt
    @WarrenLeggatt Před 3 lety

    The logical conclusion of this is map/bind or Select/SelectMany in Linq. Linq is similar to F# and Haskel "do" notation, you just need to provide the bindings. I have a library of monadic computation I use in C#. My Either object is like Result in your middle example and Result when reduced to a discriminated union is actually OneOf when you think about it.
    With Select/SelectMany bound to the valid state you could then write code like
    public OneOf CreateUser(User user)
    => from _ in IsValidEmail(user.Email)
    from _ in IsExistingEmail(user.Email)
    from addedUser in _users.AddUser(user.Id, user)
    select addedUser;
    And this hides all the "if" noise and leave just what is happening, if the validation steps fail it short circuits and returns the fail state otherwise you get the user in the valid state :)
    Linq is not just for IEnumerable when you push more functional in your C#
    :)

    • @nickchapsas
      @nickchapsas  Před 3 lety

      I personally don't that approach for two reasons. Firstly you introduce unnecessary nesting which complicates the syntax and I also personally hate the "sql like" flavor of Linq. The second one comes down to purely personal taste but the first one is also a complete dealbreaker for me.

    • @WarrenLeggatt
      @WarrenLeggatt Před 3 lety

      @@nickchapsas fully understand. I got used to it via f# do notation and got to like it. Does mean new people in need to understand more concepts

    • @WarrenLeggatt
      @WarrenLeggatt Před 3 lety

      @@nickchapsas with the sql lite link i only fall back to it for monadic bind or if the linq stack needs to capture variables from higher up

  • @RM-14js
    @RM-14js Před 3 lety

    do you recommend using Rider in Windows 10? or should i stay with visual studio 2019?

    • @nickchapsas
      @nickchapsas  Před 3 lety +1

      I absolutely love Rider but it might be for personal reasons. I also write Java and Kotlin so I also use Intellij which means I can share my settings between the two and I also use a Mac which means I get the exact same experience across all of them. I also prefer Rider's performance and intellisense over VS.

  • @Bupyc2007
    @Bupyc2007 Před 3 lety

    What theme do you use in Rider?

    • @nickchapsas
      @nickchapsas  Před 3 lety +1

      I did this a long time ago but I think i recreated the visual studio dark one

  • @janoslaszlo3272
    @janoslaszlo3272 Před 3 lety

    Out of these 3 ways you presented, which one do you use?

  • @torbjrnholtmon7195
    @torbjrnholtmon7195 Před 3 lety

    Thank you so much for the tutorial!
    Me and and my colleges discuss this topic very often. We never land on a definitive answer on how we should handle it.
    We often go the Result route, but it has its problems, and sometimes it can get tricky to onboard and convince other developers to use it.
    I dream of one day to have an "definitive" answer on how to tackle this topic.

    • @nickchapsas
      @nickchapsas  Před 3 lety +3

      The beauty or problem with programming (depending on how you see it) is that for some things you can have your own flavour because there is no definitive answer. There are requirements (functional or non functional) that might force your hand to make some decisions but you will always have your own opinion and your own way of doing things. I like to describe "Definitive" in programming as the thing that the least amount engineers complain about.

  • @felipesuarez6564
    @felipesuarez6564 Před 3 lety +2

    You said that the OneOf approach to handle errors was nice but not your cup of tea. What is then your preferred alternative to handle business validations/errors in C# ?

    • @nickchapsas
      @nickchapsas  Před 3 lety +7

      I am actually planning to make a video for this one so I won't spoil it just yet :D

    • @felipesuarez6564
      @felipesuarez6564 Před 3 lety

      @@nickchapsas looking forward to it!

    • @joelhutters4025
      @joelhutters4025 Před 3 lety

      Nick Chapsas Your videos are great, and I am really looking forward to the one with your prefered choice.

    • @joelhutters4025
      @joelhutters4025 Před 3 lety

      Waiting for this cliff hanger. Would you mind to share your preferred approach beforehand? Link reference etc?

  • @aderitocruz6054
    @aderitocruz6054 Před 3 lety

    Could I compare it with Tuple? For what I see its almost the same except in the return that u have to code some condition make it equal

    • @nickchapsas
      @nickchapsas  Před 3 lety +1

      You cannot because in a tuple you can discard parameters. You don't HAVE to deal with all the tuple values.

    • @aderitocruz6054
      @aderitocruz6054 Před 3 lety

      @@nickchapsas yes indeed

  • @konrad8015
    @konrad8015 Před 2 lety

    You have mentioned it's not your personal favourite way of error handling. What is your favourite then and why?

  • @IMarvinTPA
    @IMarvinTPA Před 2 lety

    I don't understand where the names "user", "email", and "exists" came from at czcams.com/video/r7QUivYMS3Q/video.html These seem to have come from nowhere and have no types. My only working theory is that the names are the last camel-cased word in the type, lower-cased from the OneOf declaration. How does it know how to match these generic words?

    • @IMarvinTPA
      @IMarvinTPA Před 2 lety

      Match(...) is order dependent. The first function always matches with the first Type, second function matches the second type, etc. I am not fond of order dependent things once it passes about 3. Type of the variable names being created is implied by the position in the Match method. (I want a Match method where you explicitly type the main variable and can put the functions in any order because of it.)

  • @atrumamantus
    @atrumamantus Před 3 lety

    Interesting, but the added complexity from essentially multiple return types with type based branching doesn't quite seem like a good trade off to me. Also, I know it's just an example, but this code is doing a lot of things: validations, duplicate entry checks, entity creation. Honestly I'd look more at breaking this up into different layers that handle their different logical concerns separately.

  • @alexgjo3132
    @alexgjo3132 Před 2 lety

    Throwing exceptions when validating a request is bad, but I also don't like this approach with OneOf either. A combination of custom result object and Fluent Validation is what works best for me.

  • @andriizahr448
    @andriizahr448 Před 3 lety

    But what about the Single Responsibility Principle? One method is able to return one of 3 different types instead of 1. It is not a good idea

    • @nickchapsas
      @nickchapsas  Před 3 lety +1

      Single responsibility said that the method should DO one thing. Not return one thing. For example if you returned a single object that based on what is null in the object you take different decision then do you honor single responsibility? It's the same thing and SR isn't being violated by the usage of oneof.

    • @andriizahr448
      @andriizahr448 Před 3 lety

      @@nickchapsas thanks for detailed response

  • @anju313
    @anju313 Před 3 lety

    This would increase complexity on the client side as they might also need to use OneOf to match multiple responses from a single endpoint.

    • @nickchapsas
      @nickchapsas  Před 3 lety +1

      The client side doesn’t need to know anything about how the server side is dealing with the requests internally. You just have your regular expected contracts. There are multiple public APIs that do the same thing behind the scenes but the consumers know nothing about it

  • @LuigiTrabacchin
    @LuigiTrabacchin Před 2 lety

    Maybe with code generators it will be possible to change those isTn in something more fluent...

  • @MrSuneF
    @MrSuneF Před 2 lety +3

    I would advice against this approach, for a few reasons. One is it appears to create more complex code. What you want it is focus on the main success scenario and not worry about about all the alternative flows with failures. Here the problem is it forces the caller to handle not just 1 result but multiple results. Imagine if you have a function that calls a function that calls a function etc.... With exceptions you can throw an error and handle it in the exception filter. Here you would have to handle it at every level as alternative scenarios. Usually you want logging when there is an error. With an exception filter you can put the logging in a single place, here you would have to put it into all actions in all controllers. Another reason I don't like this approach is that it sort of mixes errors with successes in an unclear way. Everybody knows an exception is unexpected, it's something we developers see as a red flag, something that needs investigation. Here it sort of legitimizes errors by elevating them to objects/structs on equal footing with successful responses, I think that is just a really bad idea. Just my 0.02.

  • @jfevia
    @jfevia Před 3 lety

    I fail to see how this is a fair comparison. Creating new structs and using a custom implementation of pattern matching isn't really that much different from having a base type and returning a concrete implementation, then using built-in pattern matching features with minimal performance hit. Also, while it's true that this enables the use of more strongly typed code, someone could end up with too many types returned (although that would be a code smell).
    Overall this feels unnecessary...

  • @IvanAndreev91
    @IvanAndreev91 Před 2 lety +1

    Why don't we use some IoC provider or other DI tools in this case? Is "OneOf" really better?

    • @nickchapsas
      @nickchapsas  Před 2 lety

      What does IOC and DI have to do with what’s discussed in the video?

  • @AndersBaumann
    @AndersBaumann Před 8 měsíci

    This is a misuse of exceptions. Exceptions should not be used for validation. No invariants have been broken. Use the Result class instead. Exceptions should only be thrown in the domain model when invariants are about to be broken.

  • @TheEvilVir
    @TheEvilVir Před 3 lety

    I don't like it. First of all throwing an exception properly breaks the ASP.NET's execution pipeline. Middleware, that is set to run after controller, has obvious and generic way of choosing if to skip or use different execution path, in case of an exception. When you return a object just with different value, plenty of middleware out there will execute happy path even if controller failed.
    Likewise your API will now have two concepts of errors: yours OneOf and standard exceptions thrown by middleware.
    Also it makes code less readable.

  •  Před 3 lety +1

    From a clean code perspectie is not a good practice to have more than 3 generic types in any class, so ... this won't cut it for me in a real life scenario. It 's nice but not useful when you have 10 different responses in a service (400,422,403,409, etc...) you would end with OneOf.... .this is not practical.

    • @nickchapsas
      @nickchapsas  Před 3 lety +1

      You can use the OneOfBase class to implement and create classes that contain and hide the number of generics.

  • @whoiam6395
    @whoiam6395 Před 3 lety

    I always putting like by default, even not going to watch video for any reason

  • @rolandtennapel5058
    @rolandtennapel5058 Před 3 lety

    Stop making sense!!! 🤣 No man totally agree; Exceptions should be thrown as an exception, not as if they were some elaborate 'switch'-board. It's lazy programming and this coming from a hobbyist C# dabbler 😝

  • @endermanfromthemoon
    @endermanfromthemoon Před 2 lety

    I don't like it because on the other side (the side of consumer) it's going to be a pain to implement all these different response types from a single endpoint