The New Option and Result Types of C#

  Рет қаралды 82,510

Nick Chapsas

Nick Chapsas

Күн бұрын

Пікірлер: 489
@oussama7132
@oussama7132 4 ай бұрын
can't wait to return Task
@stacklysm
@stacklysm 4 ай бұрын
Aliases are helpful in these situations using Users = ;
@bigice7184
@bigice7184 4 ай бұрын
Lol I think people are just going to put that into a new interface to short method signatures back to normal levels.
@_iPilot
@_iPilot 4 ай бұрын
Empty enumerable is enough instead of Option. Do not return null instead of empty collection. Nick also mentioned that few times.
@cj82-h1y
@cj82-h1y 4 ай бұрын
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 4 ай бұрын
​@@cj82-h1yYou 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.
@michaeldileo1954
@michaeldileo1954 4 ай бұрын
One tip with LanguageExt options, you can switch on the Case property: Option.Case switch { User u => …, null/_ => … }
@Sayuri998
@Sayuri998 4 ай бұрын
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 4 ай бұрын
Guaranteed bug fixes 😆
@GeorgeGeorge-u5k
@GeorgeGeorge-u5k 4 ай бұрын
I tottally disagree. We are bloating .NET with pointless features. Bigger dlls, slower performance etc.
@SixOThree
@SixOThree 4 ай бұрын
@@GeorgeGeorge-u5k Thankfully you don't need to compile in features you don't use.
@gavinrolls1054
@gavinrolls1054 3 ай бұрын
​@@GeorgeGeorge-u5ki don't agree that it results in slower performance
@patrickkurmann
@patrickkurmann 4 ай бұрын
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 4 ай бұрын
Me too. This is the great library.
@franciscorusso8062
@franciscorusso8062 4 ай бұрын
Me too. Validimir is a rockstar!
@lldadb664
@lldadb664 Ай бұрын
Thanks for the pointer to this library! Do you think you will continue to use it even with the language updates?
@patrickkurmann
@patrickkurmann Ай бұрын
@@lldadb664 yes in complex projects because Khorikov's lib enables easy railway programming. Simple projects: New C# types will do.
@Masterrunescapeer
@Masterrunescapeer 4 ай бұрын
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 4 ай бұрын
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.
@GeorgeGeorge-u5k
@GeorgeGeorge-u5k 4 ай бұрын
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 4 ай бұрын
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 4 ай бұрын
@@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 4 ай бұрын
@@GeorgeGeorge-u5kBeing 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.
@Crozz22
@Crozz22 4 ай бұрын
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 4 ай бұрын
Returning result objects was one of the best things I ever did to my codebase.
@BamYazi
@BamYazi 3 ай бұрын
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
@mistrzmatik
@mistrzmatik 4 ай бұрын
Me: Nick, can I use Rust? Nick: We have Rust in C# Rust in C#:
@ochronus
@ochronus 4 ай бұрын
10/10 meme usage :D
@jongeduard
@jongeduard 4 ай бұрын
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 4 ай бұрын
// Rust: declares integer called "n" ×&÷>%>×&÷>÷[$*&$
@true_xander
@true_xander 4 ай бұрын
​@@GameDevNerdlooks very c++ to me
@ranggatohjaya5471
@ranggatohjaya5471 4 ай бұрын
let age: i32 = 0; 😊​@@GameDevNerd
@alexclark6777
@alexclark6777 4 ай бұрын
'bout time C# grew a pair of monads
@asdfxyz_randomname2133
@asdfxyz_randomname2133 4 ай бұрын
never realized that monads sounds like gonads...
@aurinator
@aurinator 4 ай бұрын
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 4 ай бұрын
C# has had monads for a long time... LINQ's built out of them.
@AdrianoKretschmer
@AdrianoKretschmer 4 ай бұрын
lol, I see what you did there...
@deeplerg7913
@deeplerg7913 4 ай бұрын
Nick is gonna milk this proposal for 10 more videos
@nickchapsas
@nickchapsas 4 ай бұрын
You have no idea
@peculiar-coding-endeavours
@peculiar-coding-endeavours 4 ай бұрын
As he should
@StephenMoreira
@StephenMoreira 4 ай бұрын
As he should.
@sohn7767
@sohn7767 4 ай бұрын
As he should
@Ruisrd
@Ruisrd 4 ай бұрын
As he should.
@chrismantonuk
@chrismantonuk 4 ай бұрын
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.
@Kotz_en
@Kotz_en 4 ай бұрын
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.
@Turko77777
@Turko77777 2 ай бұрын
With Nullable, the value either exists or does not exist. With Option I have the same, but I can also know the reason for not having it
@joshman1019
@joshman1019 4 ай бұрын
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 4 ай бұрын
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 4 ай бұрын
@@WillEhrendreich It's a fantastic language! I pair it with C# to get a lot of stuff done, and I couldn't be happier.
@VitalMiguel
@VitalMiguel 4 ай бұрын
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 4 ай бұрын
I agree. At my company, we fired all the QA teams and replaced them with pattern matching, with no more bugs.
@JollyGiant19
@JollyGiant19 4 ай бұрын
@@2SHARP4UIQ150QA and this are both arrows in the quiver of excellence. Why would you fire them??? That’s insane
@LC12345
@LC12345 4 ай бұрын
Slowing people down and preventing them from pushing code is a way to reduce bugs too
@2SHARP4UIQ150
@2SHARP4UIQ150 4 ай бұрын
@@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 3 ай бұрын
@@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.
@weicco
@weicco 4 ай бұрын
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.
@fusedqyou
@fusedqyou 2 ай бұрын
Ah yes, reinventing the wheel.
@nooftube2541
@nooftube2541 4 ай бұрын
“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 4 ай бұрын
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 .
@TehGM
@TehGM 4 ай бұрын
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 4 ай бұрын
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 4 ай бұрын
@@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 4 ай бұрын
On the other hand that "magic" implicit error handling somewhere else in the code reduces readability.
@BlTemplar
@BlTemplar 4 ай бұрын
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 4 ай бұрын
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.
@Hawkeyes1983
@Hawkeyes1983 4 ай бұрын
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!
@Sunesen
@Sunesen 4 ай бұрын
At this point, C# is pretty much turning more and more into F#. :P
@sleeper-cassie
@sleeper-cassie 4 ай бұрын
The programming language equivalent of carcinisation is that languages keep evolving towards LISP.
@JollyGiant19
@JollyGiant19 4 ай бұрын
@@sleeper-cassieLISP’s sin was always the those parentheses
@WillEhrendreich
@WillEhrendreich 4 ай бұрын
as it should.
@bbqchickenrobot3
@bbqchickenrobot3 4 ай бұрын
Thats a good thing - loved F#. Minus the missing "protected" level access
@Raminiya
@Raminiya 4 ай бұрын
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.
@LaszloLueck
@LaszloLueck 4 ай бұрын
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 4 ай бұрын
Result type has a built-in "success or error" semantics unlike Either which is just a sum without any additional meaning
@NickSteffen
@NickSteffen 2 ай бұрын
I think the most exciting part about this would be having analyzer support for ensuring all outcomes of a result or option type are handled when returned and seeing some of the older BCL library functions start returning result objects so that if you do use these objects you can link in and return them all the way up the chain. Something even cooler would be having the code analyzer tell you when a result type for an encompassing function doesn't include an error from one of it's sub types.
@bbqchickenrobot3
@bbqchickenrobot3 4 ай бұрын
So excited foe the Result and Option - Now if we can get immutable variables by default!
@evancombs5159
@evancombs5159 4 ай бұрын
Immutable by default will never happen, too fundamental of a change for it to happen. You'll need a new language.
@jongeduard
@jongeduard 4 ай бұрын
@@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 4 ай бұрын
​@@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 4 ай бұрын
@@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.
@vcrobe
@vcrobe 3 ай бұрын
Try the F# language. It has these features and many others that cannot be added to C# (like immutability by default)
@tridy7893
@tridy7893 4 ай бұрын
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 4 ай бұрын
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 4 ай бұрын
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.
@Artokieffer
@Artokieffer 4 ай бұрын
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 4 ай бұрын
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.
@Sameer.Trivedi
@Sameer.Trivedi 4 ай бұрын
At this point you C# has enough things to recreate the entire Earth from scratch.
@DaremKurosaki
@DaremKurosaki 4 ай бұрын
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 4 ай бұрын
It had from C# 2, but now there's 5 ways to do it!
@benqbenq
@benqbenq 4 ай бұрын
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.
@ekhm
@ekhm 4 ай бұрын
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 4 ай бұрын
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 4 ай бұрын
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 4 ай бұрын
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 4 ай бұрын
You mean the developer needs to decide how each function should return a particular result? How horrible!
@evancombs5159
@evancombs5159 4 ай бұрын
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.
@benmuse140
@benmuse140 4 ай бұрын
Very much looking forward to this being part of the runtime
@gileee
@gileee 4 ай бұрын
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.
@aremes
@aremes 4 ай бұрын
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.
@liquidpebbles
@liquidpebbles 4 ай бұрын
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.
@ravikumarmistry
@ravikumarmistry 4 ай бұрын
C# is slowly getting all the features that a functional code need in language itself
@obiwanjacobi
@obiwanjacobi 2 ай бұрын
I think when you introduce a Result type you should also introduce language features to promote (error) results up the call chain. Otherwise it'll get nasty. I have programmed COM in C++ where you had to check the HRESULT after every call. It can get very complex very quickly - especially when dealing with cleaning up resources. So yeah, it looks all nice and simple in the demo's but try to do a real life program and you'll see it's not that easy. Exceptions are great if you use them for the cases where the caller should not need to handle them. Only a couple of cases where you should really handle exceptions (logging is not handling)...
@ProbablePrime
@ProbablePrime 4 ай бұрын
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 4 ай бұрын
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 4 ай бұрын
LINQ syntax to the rescue
@ProbablePrime
@ProbablePrime 4 ай бұрын
@@JollyGiant19 That is fair, I just wondered if there was an approach that didn't use it.
@JeffKwak
@JeffKwak 4 ай бұрын
Wouldn't `Result` be `Result` instead of `Result`??
@WillEhrendreich
@WillEhrendreich 4 ай бұрын
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*
@CryShana
@CryShana 4 ай бұрын
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 4 ай бұрын
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 4 ай бұрын
@@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 4 ай бұрын
@@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 4 ай бұрын
@@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 4 ай бұрын
@@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
@SebGruch
@SebGruch 4 ай бұрын
Good to see, that things that I'd introduced like 10 years ago, now go into language ;-)
@King21-t7u
@King21-t7u 4 ай бұрын
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.
@carambanoescacharrado9446
@carambanoescacharrado9446 2 ай бұрын
Amazing I hope they add it soon. 🎉
@scottwalker4619
@scottwalker4619 4 ай бұрын
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
@juliendebache8330
@juliendebache8330 4 ай бұрын
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.
@nothingisreal6345
@nothingisreal6345 4 ай бұрын
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.
@mrwensveen
@mrwensveen 4 ай бұрын
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.
@pavelmaskevich7611
@pavelmaskevich7611 Ай бұрын
Isn't this exactly why the try/catch pattern emerged in the first place? Back in the day, functions would return codes, and if the code was 0, it indicated something went wrong, and so on. Now we're moving back to that approach. It's funny to see the cycle repeat
@Masterrunescapeer
@Masterrunescapeer 4 ай бұрын
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."
@valterszaluzinskis2453
@valterszaluzinskis2453 4 ай бұрын
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
@MightyNicM
@MightyNicM 4 ай бұрын
Man C# slowly becomes the new C++, it combines every possible paradigm and as a result, gets more and more convoluted.
@evancombs5159
@evancombs5159 4 ай бұрын
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 4 ай бұрын
@@evancombs5159 why not just use C#6-C#7 - when it hadn't yet become a syntactic diabetic.
@EdKolis
@EdKolis 4 ай бұрын
I thought Kotlin was the love child of a time traveling Java and a future version of C# 😂
@michael-tsai
@michael-tsai 3 ай бұрын
All this kind of fancy new C# features are pushing me towards Golang.
@Mortizul
@Mortizul 4 ай бұрын
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!
@AJax2012
@AJax2012 4 ай бұрын
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...
@tomohisatakaoka
@tomohisatakaoka 4 ай бұрын
We like it , we need this feature in C#
@caunt.official
@caunt.official 4 ай бұрын
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 4 ай бұрын
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.
@MarcelPopescu
@MarcelPopescu 3 ай бұрын
​@@evancombs5159 The orchestration pattern makes sense for distributed code, but it's dangerous for code in the same project. It's basically a method call without the compiler helping you with anything, sooner or later you're going to forget to change things properly in one place. We want to move from runtime errors to compiler errors, not the other way around.
@evancombs5159
@evancombs5159 3 ай бұрын
​@@MarcelPopescuwe must be talking about two very very different things. I'm talking about not nesting, no idea what you are talking about.
@rumplin
@rumplin 2 ай бұрын
Will be fun with IOption (for appsettings) and Option (monad)
@TheKoneko1312
@TheKoneko1312 4 ай бұрын
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 4 ай бұрын
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.
@DisturbedNeo
@DisturbedNeo 4 ай бұрын
"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 4 ай бұрын
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 4 ай бұрын
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 4 ай бұрын
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.
@jimlynchcodes
@jimlynchcodes 2 ай бұрын
Minor nitpick, but with the Option type the point is not that you HAVE to handle both cases- it's just that you have to ACKNOWLEDGE that it COULD have the other state by having to unwrap it (for example, "if let" in Rust is what could use if you actually only wanted to handle one case or the other. not sure if c# has that)
@szikig
@szikig 4 ай бұрын
How does it differ from this ? OneOf
@dbpieter
@dbpieter 4 ай бұрын
it doesn't
@fusedqyou
@fusedqyou 2 ай бұрын
`Result` returns either a result or an exception. OneOf can return multiple results, and optionally one or more can be an exception.
@GameDevNerd
@GameDevNerd 4 ай бұрын
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.
@iliqnikushev3820
@iliqnikushev3820 4 ай бұрын
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 :)
@paramjotsingh4019
@paramjotsingh4019 4 ай бұрын
I literally learned and created my own implementation of result pattern 3 days ago...
@verdurakh
@verdurakh 4 ай бұрын
Very nice, now I just wish I wasn't stuck working in Framework with strict rules on third party libs I can use
@andriiyustyk9378
@andriiyustyk9378 4 ай бұрын
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.
@MRender32
@MRender32 4 ай бұрын
I can already feel how painfully the Option type is going to interoperate with nullable reference types and Nullable
@ErikBongers
@ErikBongers 4 ай бұрын
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.
@sneffetsd
@sneffetsd 4 ай бұрын
This is really cool!
@wizarrc
@wizarrc 4 ай бұрын
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 4 ай бұрын
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 4 ай бұрын
Nope, having Option is required in some cases. Obviously Nullable and ref types do not support that
@hbjoroy
@hbjoroy 4 ай бұрын
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.
@Suriprofz
@Suriprofz 4 ай бұрын
Love either monad, a bit like option and match in rust. Wich still feels cleaner tho
@shakoomalo
@shakoomalo 4 ай бұрын
If the validations are in a separate void method and throw an exception if necessary, in this case it should return an object and check if this object has a value. It will be a little ugly
@kaidouz7756
@kaidouz7756 4 ай бұрын
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.
@davidbloom7365
@davidbloom7365 4 ай бұрын
Does the new Result type render libraries like FluentResult obsolete?
@GrzegorzGaezowski
@GrzegorzGaezowski 4 ай бұрын
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 4 ай бұрын
Yep. i’d skip this pattern until I have a really good reason to do so.
@pedrocunha4322
@pedrocunha4322 4 ай бұрын
It would be interesting to check how much performance boost we will have in the dotnet 9
@nothingisreal6345
@nothingisreal6345 4 ай бұрын
It will be minimal.
@rcherrycoke7322
@rcherrycoke7322 4 ай бұрын
Been waiting for Microsoft to add this to c# - glad it’s finally going to happen
@KasperSOlesen
@KasperSOlesen 4 ай бұрын
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.
@recycledsoldier
@recycledsoldier 4 ай бұрын
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 4 ай бұрын
It's an already established name.
@recycledsoldier
@recycledsoldier 4 ай бұрын
@@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
@SunriseTequila523
@SunriseTequila523 4 ай бұрын
Will it only be possible to return error as exceptions? As you said Nick, it is very expensive to throw exceptions
@alexanderbecker7399
@alexanderbecker7399 4 ай бұрын
The exception is created but not thrown. Side effect: ex.StackTrace will be null...
@SunriseTequila523
@SunriseTequila523 4 ай бұрын
@@alexanderbecker7399 maybe they will find a way to distinguish between exceptions and errors, because for me exceptions are really "heavy" events, like a db connection is lost... But validation for me is an error, a lightweight to let the developer know that something wrong happened but it's not critical
@asdqwe4427
@asdqwe4427 Ай бұрын
This would be great
@alex-bj1il
@alex-bj1il 4 ай бұрын
Will they migrate the standard library to union types? That seems quite unlikely, considering the amount of code that already depends on exceptions.
@sacalbal
@sacalbal 4 ай бұрын
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.
@aurinator
@aurinator 4 ай бұрын
AFAIK Rust's Tokio Crate started these Types.
@AkosLukacs42
@AkosLukacs42 4 ай бұрын
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 :)
@Ziplock9000
@Ziplock9000 4 ай бұрын
I've always done this myself with my own system rather than using exceptions anyway.
@ml_serenity
@ml_serenity 4 ай бұрын
Just a proposal still... But we can hope we get more functional goodness in C#
@user-tk2jy8xr8b
@user-tk2jy8xr8b 4 ай бұрын
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.
@mrstiflor6744
@mrstiflor6744 4 ай бұрын
Ok the Result type is neat
@armanradan
@armanradan 4 ай бұрын
They use 'match' instead of 'switch' because this feature is inspired from Rust and 'match' is the way to handle enums, results and options in Rust.
@khealer
@khealer 4 ай бұрын
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.
@SirBenJamin_
@SirBenJamin_ 4 ай бұрын
A question regarding exceptions. You mentioned that they were incredibly slow. Is this only in the case where you have try/catch handling? The reason I ask is because exceptions are used everywhere in the base class libraries. So in reality, what performance difference is it going to make if they're still used heavily in the underlying code?
@BlTemplar
@BlTemplar 4 ай бұрын
Exceptions are slow when you use them for the control flow. Imagine you have an API available for a lot of consumers and you have some SLA on the response latency. Something goes wrong, you throw the exception, catch the exception, do some handling, throw it again and finally catch it in the response middleware. It is much slower than just using Result pattern and returning the response directly. The difference between exceptions and Results won't be very noticable on low RPS but as soon as you hit high RPS you will definetly experience latency spikes if you throw a lot of exceptions. As for standard libraries, they don't normally throw exceptions.
@jackkendall6420
@jackkendall6420 4 ай бұрын
The slow part is dealing with the stack when catching exceptions. Entering a try-block has some performance implications, but quite minimal ones. Besides those things, exceptions are just normal objects.
@BlTemplar
@BlTemplar 4 ай бұрын
@@jackkendall6420 Yep. Fun fact you can throw exceptions in Java without capturing the stack trace.
@SirBenJamin_
@SirBenJamin_ 4 ай бұрын
@@BlTemplar ah ok. So a method having the code to throw exceptions when something is wrong (e.g argument exceptions) isn't the slow part, it's only when an exception is thrown and has to be handled is when it becomes slow? What I am asking I guess is .... would the generated code be more efficient if it didn't need to support throwing exceptions.
@BlTemplar
@BlTemplar 4 ай бұрын
@@SirBenJamin_ not really, throwing is the most expensive part because you have to capture the call stack. You don’t usually need the call stack for the business logic errors. Business logic errors can happen often and if you use Result instead of Exception you also get better performance.
@IcaroFelix2023
@IcaroFelix2023 4 ай бұрын
Could you some day make a video about the library C# Functional Extensions ?
@서영준
@서영준 4 ай бұрын
It's a shame that we don't have the 'static implicit operator Result(Exception e)'
@Rein______
@Rein______ 4 ай бұрын
I hope Option will have a .Map function just like the Optional in Java.
@RomainLagrange1
@RomainLagrange1 4 ай бұрын
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...
@cristiz-vf4ww
@cristiz-vf4ww 4 ай бұрын
How do you chain calls when the function returns Task of something?
@TheRAINMan059
@TheRAINMan059 4 ай бұрын
await and use parentheses
@adambickford8720
@adambickford8720 4 ай бұрын
If the c# devs are anything like java, this will be met with pitchforks and torches.
@peculiar-coding-endeavours
@peculiar-coding-endeavours 4 ай бұрын
Luckily, they are not (that's me hoping)
@shadowsir
@shadowsir 4 ай бұрын
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 4 ай бұрын
@@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 4 ай бұрын
Yeah, I've seen a lot of requests for it. So I don't expect the pitches and torchforks
@BlTemplar
@BlTemplar 4 ай бұрын
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.
@sealsharp
@sealsharp 4 ай бұрын
Nice, please steal comptime next.
@_simoncurtis
@_simoncurtis 4 ай бұрын
We would basically have unions already if they had a way of allowing you to extend the `switch` logic for your type. Like IEnumerable in `foreach`
@meirkr
@meirkr 4 ай бұрын
Is ir possible to switch on the Result same as on the Option?
@theideaot
@theideaot 4 ай бұрын
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#
@Robert-yw5ms
@Robert-yw5ms Ай бұрын
Imo you don't really show the benefit of Option which is the bind method. This allows you to chain a whole load of operations without worrying about the None/null situation until the very end.
The Pattern You MUST Learn in .NET
20:48
Nick Chapsas
Рет қаралды 94 М.
Using EF Core’s Coolest Feature to Audit in .NET
26:06
Nick Chapsas
Рет қаралды 40 М.
1% vs 100% #beatbox #tiktok
01:10
BeatboxJCOP
Рет қаралды 67 МЛН
BAYGUYSTAN | 1 СЕРИЯ | bayGUYS
36:55
bayGUYS
Рет қаралды 1,9 МЛН
Exceptions Are Extremely Expensive… Do This Instead
17:15
Milan Jovanović
Рет қаралды 49 М.
Stop Using FirstOrDefault in .NET! | Code Cop #021
12:54
Nick Chapsas
Рет қаралды 97 М.
What is Mongoose Schema and Methods || One Shot
24:13
Unemployed_Mohit
Рет қаралды 62
What’s the Result Type Everyone Is Using in .NET?
14:47
Nick Chapsas
Рет қаралды 114 М.
Coding Was HARD Until I Learned These 5 Things...
8:34
Elsa Scola
Рет қаралды 802 М.
The Right Way To Return API Errors in .NET
10:40
Nick Chapsas
Рет қаралды 65 М.
C#'s Best features you might not be using
31:20
dotnet
Рет қаралды 27 М.
Reacting to Controversial Opinions of Software Engineers
9:18
Fireship
Рет қаралды 2,1 МЛН
"You're Doing Validation Wrong in .NET" | Code Cop #023
14:44
Nick Chapsas
Рет қаралды 42 М.
Don't throw exceptions in C#. Do this instead
18:13
Nick Chapsas
Рет қаралды 264 М.
1% vs 100% #beatbox #tiktok
01:10
BeatboxJCOP
Рет қаралды 67 МЛН