Тёмный

Should you stop returning "null"? | Functional C# 

Nick Chapsas
Подписаться 304 тыс.
Просмотров 105 тыс.
50% 1

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 how we can leverage a functional concept in C# that can potentially help up eliminate unexpected errors in our system. I am talking about null and the hundreds of issues that I have personally experienced with it over the year. Let's take a look at the problem and discuss a potential solution.
Give Language Ext a star: github.com/lou...
Don't forget to comment, like and subscribe :)
Social Media:
Follow me on GitHub: bit.ly/ChapsasG...
Follow me on Twitter: bit.ly/ChapsasT...
Connect on LinkedIn: bit.ly/ChapsasL...
#dotnet #csharp #functional

Опубликовано:

 

15 сен 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 280   
@JayVal90
@JayVal90 3 года назад
I think it’s much easier to just use C# nullability syntax.
@r.c8756
@r.c8756 3 года назад
Well, quality of code sure has a cost...
@SamFerree
@SamFerree 3 года назад
With the vast amount of the BCL that was null annotated in net5 and if you treat warnings as errors (which you should) then yeah. NRT is now the a fitting, and more idiomatic c# solution.
@Luturol
@Luturol 3 года назад
even tho u have to check if has value in some cases
@mahmoudalsayed1138
@mahmoudalsayed1138 3 года назад
@@Luturol You could mark it as non Nullable reference type and throw null exception in the method, outside the method you will be 100% sure it can't be null, ergo, there is no need to check fo nulls, there is no boilerplate code.
@mahmoudalsayed1138
@mahmoudalsayed1138 3 года назад
Exactly! Not much easier, it's way cleaner to the code.
@AlanDarkworld
@AlanDarkworld 3 года назад
An important topic right there. Null values in a langauge where the type system has no notion of "nullability", null values are a liability that you have to work around, e.g. vai Optionals. In a language which has the concept of a nullable type built right into the type system (such as Kotlin or TypeScript), null values become an asset. The compiler of such a language will actually refuse to compile a file by throwing a compile error at you if you try to do anything that *might* result in a NullPointerException. This has been revolutionary for my team and for my way of writing code. This feature alone makes Kotlin vastly superior to Java. It may seem like a small thing, but the impact it has is tremendous.
@olovjohansson4835
@olovjohansson4835 3 года назад
I like this pattern and we use it a lot. Otherwise an interface does not signal whether you should check the result for null or not - you have to read the documentation, or the implementation. Nullable referense types also solves that problem
@twiksify
@twiksify 4 года назад
I remember missing an equivalent of Maybe in Haskell years ago, but have since then forgotten why. Thanks for refreshing my memory!
@superpcstation
@superpcstation 4 года назад
Hi Nick, would really appreciate it if you could increase your font size a bit. Really helps out the mobile viewer.
@davidsaunders1595
@davidsaunders1595 3 года назад
Good for you doing a video on this Nick, I come from a Kotlin environment where null safety is a first class citizen and I was blown away how much of a game changer it was. IMO the C# world has been slow to adopt the trick properly. I will say C# 9 nullability syntax with warnings as errors is what we use for this now, skipped C# 8 cause it had awful collisions with nullable struct syntax and generics. If that’s not an option something similar can be achieved with ReSharper/Rider, JetBrains Annotations and Implicit Nullability if running static analysis checks is viable. Short of that though this is what I’d use, good job.
@nickchapsas
@nickchapsas 3 года назад
It’s one of the reasons why I love Kotlin so much. With C# it’s obviously an afterthought and it’s up to the user to adopt which is understandable but sad if it doesn’t get adopted widely
@henrykkaufman1488
@henrykkaufman1488 2 года назад
Languages without null, like Rust, use exactly the same Opiton thingy. It does 3 things: - explicitly removes null from places it doesn't have to be (or would ever exist) - makes sure programmer is aware / handles the null case - makes programmer write more code Other than that, nothing changes. So generally it's safer code at cost of more code. I like these videos, they're pretty expert and unopinionated (professional). Thanks for doing this. I would love to see some material on possibilities of making sure a function won't change what you pass to it (like not passing mut in rust or using const & in c++).
@kyoai
@kyoai 3 года назад
But if you try to actually access the returned optional object, you sooner or later still have to do a check whether the object is valid or "none", so essentially it did not solve the null check problem, you just shoved the validity check to another place and did it in a more fancy way.
@SamFerree
@SamFerree 3 года назад
If the only way to access the object is by "Match" then effectively you've compiler enforced the check, since you can't call Match for the Some only case, you MUST provide a None case or it will fail compilation. It moves the error from runtime to compile time. you can also do this post C# 8 by enabling Nullable reference types and treating all warnings as errors.
@r.c8756
@r.c8756 3 года назад
The point is not to remove the necessity of checking null values but to force the caller of a function to acknowledge the fact that it can return an empty value. This is mostly a safety/readability feature.
@rolandtennapel5058
@rolandtennapel5058 3 года назад
@@r.c8756 I read what you're saying but all I hear in my head is 'People are lazy in reading and writing documentation and have very dangerous assumptions.' 🤣 But seriously, developers that want to use this have had ways of doing this since day 1 of C# (me in part). Developers that don't want to use this won't (me in another part, bit of internally (protected) split on this issue). 😉
@atrumamantus
@atrumamantus 3 года назад
@@rolandtennapel5058 it's not about being lazy, missing a null check is a common bug even for seasoned developers. Having tools to help you keep your code sound is never a bad thing, and the possibility of trading a runtime error for a compile time error is always a plus. Java has Optional types as well and they are very useful.
@r.c8756
@r.c8756 3 года назад
@@rolandtennapel5058 Documentation will never replace code quality and yes, people are lazy. They sometimes make mistakes and sometimes, they even plainly suck. This is kind of a negative way of looking at things but on the other hand, making things safe is thinking of the worse that can happen and then think of a way to prevent it to happen. As a programmer, you should always assume that the next guys who’s gonna use your code will mess up in the worse possible way. (and if you have a bit of experience in the field, you know that this happen more often than you’d hope...). So an important part of our job is to write code in a way that they can’t.
@TanigaDanae
@TanigaDanae 3 года назад
I think this is very subjective but a neat solution. Personally I like to use vanilla paradigma and since you have to rewrite all the interfaces and functions to use "Option" you end up with a "Get(...)" and a "Match(...)" function instead of your "null" check. In this specific case I could make the code "null" aware in other ways e.g. by implementing a "bool TryGet(..., out)" instead. But at this point I guess it is just a matter of taste.
@michaelgehling6742
@michaelgehling6742 2 года назад
I prefer the try-pattern with bool TryGetSomething(out SomeType result). I n this solution the decision making is also implied and I don't need any unnecessary lambdas.
@goranstefanov4531
@goranstefanov4531 4 года назад
I like the idea. Prevents exceptions and it feels like a proper approach. I would definitely enjoy more videos like this. Thank you!
@TheExiledMeriler
@TheExiledMeriler 4 года назад
I prefer nullability. And I love how null safety implemented in kotlin
@nickchapsas
@nickchapsas 4 года назад
Yeah C# was basically trying to get to Kotlin's implementation with C# 8 but the problem is that null worked like this for so many years that it's been engraved to anyone's muscle memory and it's so hard to change your mind on something that you've been doing for years.
@bradenb
@bradenb 2 года назад
I love options, but I've had a hell of a time convincing my coworkers of their value. Occasionally I'll have some beautiful, elegant piece of code as a result of using them and they'll appreciate it, but never enough to try them for themselves. I've started sneaking options into common libraries to force it though :)
@eclecticx
@eclecticx 3 года назад
'Should you stop returning "null"? ' Hell no. The mere question signifies overthinking. In regards to objects, trying to avoid null, which is there for a legitimate and useful reason, usually leads to over-programming if not bad programming. Lists are another matter. Those should always be initialized and have a count of 0 if empty.
@IllIlIIllIlIl
@IllIlIIllIlIl 3 года назад
I agree, the code is much less readable in this case. I’m all for optional values (like std::optional) but I wouldn’t use it for nullables because a nullable already has the functionality built in, ergo the ability to check for a null reference.
@r.c8756
@r.c8756 3 года назад
I really don’t understand this disposition of mind. Questioning practices is the most elementary step of learning and improving and you never stop doing that in a career. With that mindset you can never improve... In only looks less readable because it challenges your habits.
@eclecticx
@eclecticx 3 года назад
@@r.c8756 It's good to question things and consider new approaches, but you're stepping backwards if you add unneeded complexity. Less readable is less readable; that has nothing to do with habits being challenged. A software engineer, especially a contractor, can't be successful for any considerable number of years without challenging their habits, getting outside their comfort zones, and expanding their knowledge on a consistent basis. Not returning null and engineering a work around to avoid it is none of those.
@logank.70
@logank.70 3 года назад
The thing I like about the approach, personally, is that the design tells you that you have to account for "none." Nullable reference types are good for that too.
@eclecticx
@eclecticx 3 года назад
@@logank.70 Exactly re nullable ref types, so why go to the trouble of the design? Just seems to be a case of overthinking and recreating the wheel simply because the programmer doesn't want to use nullable refs already included in the framework. Besides, nullables are something every programmer should already know how to handle, even a junior one.
@alfredoquintanalopez2265
@alfredoquintanalopez2265 4 года назад
Cool video, Please continue with this functional approach it's great!!!
@fuzzylilpeach6591
@fuzzylilpeach6591 3 года назад
"not null, just the idea of no value." Pretty sure that's what null is.
@icebird76
@icebird76 3 года назад
@Ishaan Jaxtyn Insane! It took me 5 minutes to say it worked!
@tofraley
@tofraley 2 года назад
You'd be incorrect. That's not what null is. The type system does not give us a way of representing "nothing" or "no value". So we use null to do that, even though it's problematic. And since everybody has treated it that way for so long, the compiler team had to create work-arounds so people would stop hurting themselves with it.
@WarrenLeggatt
@WarrenLeggatt 3 года назад
Null is not an issue, it is the lack of self documentation in the function signature public MyClass GetTheThing(); This function can return an instance, a null or throw an exception but you have no idea looking at the sig. This can mean people do not handle the possible outcomes. This is actually the correct signature such that just looking you can determine what can come back. public Either GetTheThing(); C# 8 with nullable reference rates part of the pain out as you know if its nullable. The more info devs have on what can come back the less risk of blow up when in production :)
@frotes
@frotes 3 года назад
Good stuff, I think functional programming patterns are great stuff that leads to cleaner and more expressive code, with less chance for bugs. C# is becoming more functional with every release. Would love to see more content in that direction on how to setup/utilize constructs like different monads and circuit breaker patterns.
@the-matrix-has-you
@the-matrix-has-you 4 года назад
Tony Hoare has said "null was my billion dollar mistake" but I don't think he was right about that sentiment.The Programming World needed a Universal Type that reflects empty, has no members words in a simple way so we came Up with Nullable so that way any Type can be nullable the class looks for if the passed object is initialized or not and if initialized does it have a value set to it if yes then it is not null. So it was the Best way to do it really. Besides the whole .Net Framework Technologies depends on the Nullable Type there is no easy way of changing things now. I don't even mention the zillion of programs all around the World that is on production heavily depends on Nullable Type...
@SeanJMay
@SeanJMay 3 года назад
There are no safe operations on null, though. That is the difference. The world does need some Empty or Bottom type. That should not be a type whose default behaviour is to go kaboom, though. It's a type whose default behaviour should be a no-op, with a reminder to deal with the no-op, *without* encouraging people to just swallow catches, or return null to the next poor sap who needs to do the exact same things you just did... possibly without the same level of concern for soundness of the logical flow of the application.
@filipecotrimmelo7714
@filipecotrimmelo7714 4 года назад
I really like the idea. It prevents exceptions in the code, also leting new programmers doing less errors;
@amuuuinjured
@amuuuinjured 3 года назад
In that case - better way to prevent new programmers from doing errors is not allow them to code. :D
@filipecotrimmelo7714
@filipecotrimmelo7714 3 года назад
@@amuuuinjured LoL
@MoMadNU
@MoMadNU 3 года назад
Spend twice as much time testing than you do coding and it won't matter. Either you coded for null or you didn't and if you didn't it's a bug that you must fix.
@berylliosis5250
@berylliosis5250 2 года назад
@@MoMadNU Why waste time testing things the compiler can trivially verify for you? Test time is better than runtime, but compile time is better still. (Not to mention the more explicit/correct API)
@MoMadNU
@MoMadNU 2 года назад
@@berylliosis5250 The compiler cannot detect a null reference exception which represents 90% of the exceptions you will encounter because of bugs in your code.
@aurinator
@aurinator 2 года назад
Full Disclosure posting before watching video, but my initial reaction is that it isn't as long as that behavior is expected from whatever's returning null, as while I completely agree that it isn't necessarily optimal or desirable per se, I've seen it used to make variables effectively ternary values when null is used, and it worked very well, but it was similarly documented well enough that the behavior was expected. I'll update this after the video if my opinion changes. Thank you so much for explicitly touching on that there *WAS* indeed a way with Unsafe code though. Burying heads in the sand around those possibilities doesn't make them go away, but many have done it from my experience.
@alexanderhugestrand
@alexanderhugestrand 3 года назад
The only difference between returning null or to use "maybe", is that the latter gives you compiler assistance to enforce you to write that if/else statement that you would otherwise forget. Personally I think it's overengineering to use such a construct. If/else works just fine if you are disciplined enough and test your code before deployment.
@Kokujou5
@Kokujou5 2 года назад
wow... someone never saw C# colesce operators... outch... guess that hurts now^^ return customer ?? Notfound(); and this can be valid syntax because if your method is an ActionResult you can directly return T and it will be converted into an OK
@jacobstamm
@jacobstamm Год назад
It would be so cool to see a round table discussion between you, Zoran Horvat, and someone like Eric Lippert or Anders Hejlsberg discuss the merits of nullable types vs the Optional pattern in C#. There seems to be some degree of dogmatism around it and it would be nice to see that stripped away.
@coso2
@coso2 3 года назад
I still love use and return null :) But, from an execution perspective, which method is better on memory and execution speed?
@BonBaisers
@BonBaisers 3 года назад
I use it on UI layer and Features layers (CQRS). Nulls and Exceptions are reserved to Infrastructure layer. Everything up must use Option like class type of response to force my devs to handle all cases on the application domain and the UI.
@bruceleggett7500
@bruceleggett7500 3 года назад
I agree that nulls are a multibillion dollar mistake due to finding null reference exceptions in the Production environment sometimes for edge case scenarios and other times deep within a property chain which takes some extra time to debug and resolve. The use of the generic Option class isn't the elegant solution I was expecting. I was expecting Options to be built into the language and complier itself and include extra option functions and syntax
@sonicbhoc
@sonicbhoc 3 года назад
That was one of the first things I noticed when I played around with F#. Option is built-in.
@rolandtennapel5058
@rolandtennapel5058 3 года назад
Not for me, but I get it and I appreciate it 😏 I guess I'm just too comfortable with assuming anything / everything can be NULL and check for it (or pass by reference which helps a lot).
@masterdju1
@masterdju1 3 года назад
And its simpler to check if null... In thus case we need to use additional library and still write some checking code
@rolandtennapel5058
@rolandtennapel5058 3 года назад
@@willembeltman Checking inside the function means you don't have to remember to check outside the function. 😉
@aborisov20
@aborisov20 3 года назад
I prefer always return IEnumerable even when just one object is expected. That solves the "returning null" issue. When no object found you will get empty collection.
@SamFerree
@SamFerree 3 года назад
Option is basically just a list of 0 or 1. Some implementations of option actually just extend IEnumerable and essentially just provide convenience methods for returning a list of 1 or 0
@r.c8756
@r.c8756 3 года назад
It works but it’s a (dirty) hack which damages the readability of your code. The very point of typing is to add meaning to otherwise completely abstract and decontextualized algorithms.
@aborisov20
@aborisov20 3 года назад
@@r.c8756 Disagree with the first sentence and agree with second sentence. :)
@r.c8756
@r.c8756 3 года назад
@@aborisov20 Returning an IEnumerable tells whoever read your code that they should expect several elements. This is deceitful and therefore, bad practice. Correct use of types, variable and method name should describe as accurately as possible their behavior... What do you disagree with exactly ?
@aborisov20
@aborisov20 3 года назад
@@r.c8756 Nothing related to term "dirty hack". Just expected behaviour. By design.
@user-hz1yc6cw6k
@user-hz1yc6cw6k 3 года назад
It is a big mistake to think that replacing null with custom value gives you anything valuable. You will not avoid exceptions, or even worse, you will get weird behavior and one more elusive bug in the tracker instead of a simple exception pointing you to exact number of the string where it happened in the code. Plus, with Nuget package like this one, you will get worse performance because there is additional structure requiring additional memory and comparison with custom value of None instead of hardware optimized comparison with null.
@nickchapsas
@nickchapsas 3 года назад
Based on my personal experience in the past 2 years, it’s very much the opposite actually. It has completely removed any NREs, the code it way more predictable and deterministic and the performance degradation is so slim it’s not even a factor. Not only that but since these types are structs there is minimal memory footprint changes.
@user-tk2jy8xr8b
@user-tk2jy8xr8b 2 года назад
It was a big mistake to make the nullability (and omnipresent `default`) concept core to the language. Could you provide an example of weird behavior with Option? Besides nulls being converted to None.
@fishzebra
@fishzebra 3 года назад
Thanks nice simple demo. I really like Option, however now C#8 has Nullable Reference Types there is less of a need for it. And as brilliant and extensive as the LanguageExt library is, it encourages C# developers to go deeper into using other Functional concepts which could easily confuse other team members and create unreadable code. Hopefully one day Option is built into C# and then we can freely use it, otherwise there is an argument that if you want to do real functional programming then you should stick to a Functional language like F#. I think this is valid, but it also frustrates me as there are not many F# jobs out there.
@brianm.9451
@brianm.9451 2 года назад
I really like this approach. Wish I implemented it on a project since dealing with NULL’s was a huge pain for my app.
@zubairkhakwani8772
@zubairkhakwani8772 Год назад
If we have to operate on an object we're getting from DB, we still have to check for null before using it (In service or in the controller). So how does it benefit? I will still try it and see If it helps.
@bernardoherrera5217
@bernardoherrera5217 2 года назад
I love functional programming, I programmed for more than one year in Scala then when I came back to C# 4 years ago I found that there weren't so many functional features built-in the language itself. But now the language it is envolving and that's a good thing
@RicardoValero95
@RicardoValero95 3 года назад
Hi Nick, about your api route I've been having issues using guid type as a parameter (invalid guids return oks), but as I saw in your example you parse it in the controller. Is this the best way to do this?
@ChrisWalshZX
@ChrisWalshZX 4 месяца назад
Is there any inefficiencies introduced to using Option? You say it's a struct but there must be somewhere where a reference or a no-reference is indicated that doesn't occur with null and not null. The code is also more verbose than traditional use of null and compiler helping with Object? vs Object helps identify and remove bugs during dev. Not convienced yet but interested in your further forays into Functional Programming. Thanks Nick.
@JohnEBoldt
@JohnEBoldt 2 года назад
Update: I discovered the IfSome method which is exactly what I need for my use case. So no unsafe! I like this approach! I do have a use case question though. In my repository layer which uses EntityFramework, some columns are nullable and so if a property is null, I need to return a null value. I can do this using MatchUnsafe, but I'd prefer not to use it unless I have no other choice. Is there a better way to do this? Example: ExternalUserId is a string property in an EF table that is nullable in the database. ExternalUserId = user.ExternalUserId.Match(e => e, (string)null); This throws an exception when returning null. ExternalUserId = user.ExternalUserId.MatchUnsafe(e => e, (string)null); This works, but I'd prefer not to use it. Thoughts?
@samuelgrahame3617
@samuelgrahame3617 3 года назад
Use null if needed. Check for null. Or use not null option.
@masterdju1
@masterdju1 3 года назад
But whats wrong with null check? Why do we need to complicate code for a simple thing? In any case we should check if null or if match
@user-tk2jy8xr8b
@user-tk2jy8xr8b 2 года назад
You can avoid null check, but cannot avoid match
@MartinMaat
@MartinMaat 2 года назад
You need to see some code for this to make sense. I have had discussions about this on SESE and they went nowhere. It only gets meaningful at 9:45. Before that one can just go "So it won't blow up at the same point, it will continue to run in an undetermined state which is worse! You will have to check at some point, whether it be for null or None...". Obviously for fluent interfaces null is literally a show stopper, I got that. Now I also see the returned wrapper object forces you to obtain the (encapsulated) value in a safe way. This is the real boon that often gets lost in a focus on null itself.
@Ownage4lif31
@Ownage4lif31 3 года назад
Thought this was a joke, turns out you got a point. Thanks
@arunbm123
@arunbm123 Год назад
brilliant, its clean way to return from Action Method
@sadux
@sadux 3 года назад
Great Chanel and tutorials. Thank you for sharing your knowledge. Keep going!
@Luturol
@Luturol 3 года назад
Great video! I was always wondering if C# had a similar to optional from Java
@wordonice4457
@wordonice4457 3 года назад
Null for life!!! lol but this is quite nice. I'll check it out. Looks like the optional interface in Java, which I've used a lot
@fullmoonyeah1180
@fullmoonyeah1180 2 года назад
at the end of the day, it depends on how the value is treated. it also has some benefits that developers can use with it.
@marsovac
@marsovac Год назад
I don't like this if I have it in the interfaces, because it makes the nuget a requirement for implementing them, and sometimes that is not allowed. So yeah, nice to remove "if (x!=null)" and convert it into something more explicit, as long as it does not have repercussions down the chain.
@dcuccia
@dcuccia 3 года назад
C# 9 switch expressions are a nice built-in implementation of Match.
@logank.70
@logank.70 3 года назад
I use switch expressions all the time now. C# 9 makes writing functional code in C# much easier.
@666marat666chanel
@666marat666chanel 3 года назад
first you saying that we need specific handling of null case but then you do same, you specifically handling null case but it will be converted to null and has different syntax don't see really a big difference to be honest maybe on bigger example it will make sense
@nickchapsas
@nickchapsas 3 года назад
One is optional one is mandatory. That's the difference.
@11r3start11
@11r3start11 4 года назад
I prefer to use functional syntax, its a lot more readable, though its harder to understand what's going on inside. But I'm wondering, how much overhead does Option usage have? especially .Match call with lambda-parameters
@nickchapsas
@nickchapsas 4 года назад
Very good question. It's my bad that I didn't cover it during the video. On this specific example: The Non-Option approach will execute at a mean time of 146 nanoseconds and will allocate 168 bytes of memory (it's probably the Guid object allocation). The Option approach will execute at a mean time of 222 nanoseconds and will allocate 296 bytes of memory (it's the Guid plus the Option object, even though this is stack memory allocation due to Option being a struct)
@WarrenLeggatt
@WarrenLeggatt 4 года назад
With the latest C#, if enabled, there is nullable reference types similar to int?. With this all reference types by default are not nullable which can mitigate much of this out and the time implications will be reduced. When you use nullable reference types you have the same .HasValue and .Value properties along with operators like ?? and .? Personally I have come around to null is evil. I have lost count of the null exception errors I have chased down over the decades I have done at the code face. It is far better to use this sort of technique to force devs to have to deal with the full types of the return value instead of mask it. If you get an Option or MyClass? returned you know you have the chance you have no value and are forced to handle it. If you just get MyClass returned without that protection you have no idea. It makes the function more explicit. Take the following public Result DoTheThing(); You can instantly see you might get a "good response" that might have a value or you get an error. No need to dig into the code to see if it can throw etc
@OldShoolGames
@OldShoolGames Год назад
What about throwing a custom exception and catching it at an upper level ?
@sidfjames1076
@sidfjames1076 Год назад
Since new null checking feature in dotnet, which can be set to an error, I think the issue with returning null is (pun intended) "null and void".
@jasalvador
@jasalvador 4 года назад
Great video! But it's not almost the same on using c#8 Nullable reference types? I don't know how c#8 nullable exactly works, I think only throws a warning when compiling but actually it compiles. In that case, I agree with the use of Option. If we could make that the code does not compile, It would be right to use the nullable type right?
@nickchapsas
@nickchapsas 4 года назад
The thing with Nullable reference types is that it doesn't really prevent you from handling them. You can still use the bang operator (!) to suppress it and it's not an error until you explicitly mark it as one. It's basically an afterthought and realistically, people won't instantly jump into using it because they can get away without using it. Option is something that you need to acknowledge no matter what, which i prefer.
@mariacobretti
@mariacobretti 4 года назад
@@nickchapsas this is a very interesting discussion and maybe worth picking up in another video showing the approaches side by side with a more complex example. I'm currently leaning towards nullable reference types because I have seen code with pretty big classes and handling the matches made it quite difficult to read and understand. And with a good culture where you try to eliminate all the warnings I think its nice for a lot of cases. Also I just remembered that you can install the FxCop nuget package and have the null reference warnings pop up as errors instead so the project does not compile.. I probably should try that
@carlinhos10002
@carlinhos10002 3 года назад
You can configure the code to not compile if there are such warnings, and if one use ! forging operator, well, what he's saying is that "ok, I know it can be null but I don't care" which doesn't mean he forgot about null-check, pretty much the opposite. I think using yet another library to handle a case that's already done by the language is just too much. It was useful before c#8 but now it's just more complexity
@cs96ai
@cs96ai 2 года назад
Great video! Would be great for generating object model audit trail. Keep up the awesome work! Any plans to do Kubernetes, Swarm, rancher?
@DanteDeRuwe
@DanteDeRuwe 4 года назад
Thanks Nick for another insightful video
@fourZerglings
@fourZerglings 3 года назад
Should you stop returning null? Yes. Replace them with Optional.
@amuuuinjured
@amuuuinjured 3 года назад
1. What that code will look like when there will be two separate repository calls? Let's say get two different customers and return Ok only when both exists. 2. That library seems are over complicating things. If you need that Match method - write simple extensions method and check if value is not null call ok otherwise fail.
@morlock2200
@morlock2200 2 года назад
the only way i use null atm is if i got an method that i want too have 3 values where 1 might be null cause i only wanna use two, i prefer makeing an class where i can return a bool and a message(string) back and do stuff with that. so even if the return is null it means the bool check for if it´s true so if it returns as null it would run the "Failed" code and just say " it failed".
@GregWilliamBryant
@GregWilliamBryant 2 года назад
@Nick Chapsas - I would be curious to how you feel about this style in 2022. I've unconsciously implemented something very simular in my codebase and really like this style personally.
@JSDudeca
@JSDudeca 3 года назад
I would say yes but I don't code in C#. I always return some sort of "None" type reference. Does not matter what language I code in. For a strong typed returns like Java, I would subclass the return type to identify value like NullMap for returning a Map that is "None". Never done C# though.
2 года назад
I prefer not to return null when possible. I also try to avoid nullable value types.
@Rokannon
@Rokannon 3 года назад
2:35 Flag 'found' is redundant. You can just: _customers.TryGetValue(customerId, out var customer); return customer;
@daneru
@daneru 2 года назад
For an API i would never use null return value. I'd return and object with some kind of warning message with 400 or 500 status code. So the recipient understands what happened. Also, the response is going to be handled differently because the status code is not OK. Inside assembly i think it is okay to use null. The key is to be consistent which is harder to reach working as a team.
@ckjdinnj
@ckjdinnj 3 года назад
The options semantics is a bit obtuse. The exact same behavior is achievable in a clearer manner. The interface method should be changed from: Option Get(GUID id) ; To: bool TryGet(GUID id, out Customer customer); The first one has obfuscation that hurts more than it helps. TryGet signatures are clear and automatically enforced by proxy of out parameters requiring assignment by the compiler.
@gardian06_85
@gardian06_85 3 года назад
I just get the feeling that if it is "none" then it has the form of the object, but could be uninitialized, and could kind of be more dangerous. if the code attempts to access an uninitialized field then it could lead to bad results, but if it tries to access null then it throws an exception. is it possible for a none to be modified into a real version of the struct/object. I just get the feeling that if it can be modified at any point then bad out of bounds data could cause bigger problems and maybe volnerabilities rather then the program hitting an Exception.nullReferenceException
@SeanJMay
@SeanJMay 3 года назад
These containers aren't for low-level operations, and aren't for async values (that last part isn't exactly true... *this* container isn't for async values... async/await itself hides the concept of containerizing requests), they're for code composition. At any point in your example, some programmer could have your instance mutated by 8 different threads at the same time, with no thread locks; how is null going to help you in that case? If that's how your team writes code, then nothing can save you. The class is already there and uninitialized, or poorly reconfigured. If my code needs to return an A, but in order to make an A, I need an x which I have, and a y which I don't, I can solve that in ways better than passing around uninitialized instances. async GetA () { x = GetLocalX(); potentialY = await GetY(); potentialA = potentialY.Map(y => new A(x, y), None); return potentialA; } I am only going to make an A in the case that I know I can correctly construct that instance. And what the next user gets is something that they can operate on (through Mapping from A -> B), Filtering from (A -> None) in the case they aren't interested in that instance, handling the case where they got nothing, or just passing it on to the next person down the line, who will do any or all of the above, before themselves passing it on. It benefits the system in general, to write it in such a way that you have no incomplete or ill-configured objects/structs/sets/etc floating around, regardless of what architecture you're using for code composition.
@tofraley
@tofraley 2 года назад
"None" does not have the form of the class you are trying to access. Lets say you have a method that returns an object of type Option. If you call that method, and it happens to return Some, you can think of that as wrapping a Person object. If you want to use that object, you kinda have to reach in and get it. In other words, you can't just treat the Option object like it's a Person object. On the other hand, if you call that method and it happens to return None, there is no Person object to access. In reality, that Option is probably wrapping a null Person object. But that's just an implementation detail, you have no way of accessing it. You can't accidentally access it. People in these comments seem to think the point is to have a clever way around null checking. That's not it. The point is to have a real representation of "no value" without bringing null into the equation at all.
@diegogarcia6518
@diegogarcia6518 2 года назад
I like this video, and it's a cool package; but my two cents are that NRT's were enough for most scenarios back when the video was released, and with the upcoming .NET 7, auto-implemented null checks will make it even more so. This further adds to boilerplate in recent versions, but if you're stuck with legacy, this package could be a god-sent
@archstanton9182
@archstanton9182 2 года назад
My coding standard insisted that a function only has one return path. Multiple return paths can be confusing, especially if it is code you inherited from someone else who has left the company.
@gleamofcolor
@gleamofcolor 4 года назад
Thanks for the video . why don't we add that option just before the return statement where we needed as I don't like the idea of changing the return type everywhere. If I want to share the logic between the module , how that works as it don't expose the object as it is.i need use some method in the option struct to get the retuning object value .it's unnecessary overload and performance issue as well.
@nickchapsas
@nickchapsas 4 года назад
Maybe this example doesn’t illustrate the point as well as I’d like it to because it’s a very simple example. Realistically you would have different return types on each layer and you wouldn’t just be able to return option itself. The whole point of option is that you cannot get the value without handling the None scenario and that needs to happen across your application. Also, like I said in a different comment, performance impact is negligible.
@gleamofcolor
@gleamofcolor 4 года назад
@@nickchapsas thanks, it would be great if you have another video which covers the said point.
@airjuri
@airjuri 3 года назад
@@nickchapsas "performance impact is negligible." Famous last words before performance issues commmence ;)
@nickchapsas
@nickchapsas 3 года назад
@@airjuri I can guarantee with 100% confidence that this will be the last thing that you will need to optimize in your application
@ByronScottJones
@ByronScottJones 3 года назад
If you're getting null reference exceptions, it's because you're not bothering to check for them in situations where they are a possible, and valid, return result. That's a programmer problem.
@aleksanderw5536
@aleksanderw5536 3 года назад
Hi, considering that C# has nullable types which if used can lead to eliminating null pointer exceptions as well, do you think that Option still has a place in there?
@nickchapsas
@nickchapsas 3 года назад
I do actually and I see them as a different thing. Nullable types and the compiler can lie and Jon Skeet has a great talk about that. It’s also to the library author’s discretion to use them. Option beats all that with a clean forced matching scenario
@alpyre
@alpyre 3 года назад
I am a C programmer and watch these videos for fun... ...and in each of these I get the feeling that these modern language standards are trying to solve problems that are not problems in the first place... ....aand most of the times the solutions are worse. :)
@nicholaspetersen1629
@nicholaspetersen1629 2 года назад
👆👆 yep. what’s worse about this is these cultural forces (not the beautiful language itself) ends up ruining the language in practice (because to use it you have to work in environments with such enforced paradigms), so then we all have to go back to C to escape this!
@JonathanPeel
@JonathanPeel 2 года назад
I do like this (and I use F# a lot, so this makes a lot of sense), however, I think with the newer C# nullable `Customer?` I don't think it is needed. The language will force us to handle the case where the value is null. If we are handling a nullable, or we are handling an Option we are still handling it. I also like the idea of `map` and `bind` functions but we can also create those for Nullables just as easily as we can create them for Options.
@nickchapsas
@nickchapsas 2 года назад
It will only force you if you enable nullable reference types as errors in your project and even then you can ignore if you if think you know better than the compiler with the ! operator
@JonathanPeel
@JonathanPeel 2 года назад
@@nickchapsas Yes, that ! is true. I do that 😝 But usually, only in cases I know would have had an error a long time ago if what I am accessing is null. Maybe it proves your point. I have never seen the language extension library you talk about. I might check it out, although like I had said I use a lot of F#, so I might have a method returning FSharpOption or FSharpResult. This library probably wouldn't work on those.
@ericfelipe2011
@ericfelipe2011 3 года назад
You do a simple IF in first code... But now, you generate a struct that consume memory and it's not a reference type, so, the object is copied in all return, plus you need two lambdas that's generate a lot of process and context keep process.... Why this is good ??? You need more memory, more process, more processor stack, and so on....
@nickchapsas
@nickchapsas 3 года назад
Because your code is safer. The benchmarks show a performance degradation in the class of a few nanoseconds for the benefit of NRE elimination and for predictable code. Ofc it’s something you can ship if you commit to using null reference types properly but again that’s up to the dev
@ericfelipe2011
@ericfelipe2011 3 года назад
@@nickchapsas if you put a check for null. Where the dangerous path of that ? Plus this nanosecond with a Friday, science software, bi software, financial software... And of course, change all your code... It's the basic of a language null treatment.... It's like... We are using a stable old fashion jeans... Let's create a radical new one.
@nickchapsas
@nickchapsas 3 года назад
@@ericfelipe2011 The dangerous part is that it's up to the developer to put the null check in. What you're assuming is that every nullable thing will be null checked at the right place, which is simply not true.
@ericfelipe2011
@ericfelipe2011 3 года назад
@@nickchapsas with new coalesce it's even simpler Return object?.property ?? New list() With so many code analítics, it's can be configured yo show a warning of a null reference or something.
@nickchapsas
@nickchapsas 3 года назад
@@ericfelipe2011 Coalesce is a completely different feature and has nothing to do with this. I agree that Null reference types can be configured to give a similar experience but it's still up to the developers and the team to enable it and make it mandatory (error instead of warning)
@fat-freeoliveoil6553
@fat-freeoliveoil6553 2 года назад
I think it is a nice feature but I don't think I'll use anything like this unless it is part of .NET. I think having dependencies like this is a bit problematic. Doesn't nullable reference types basically solve the same problem anyways? You are telling the developer and the compiler that this can be null and thus should be checked (fortunately, Rider and VS also tell you this). (I get that some developers aren't comfortable with moving to a nullable project since it is a bit difficult to transition to but it is there).
@ilove2learn783
@ilove2learn783 2 года назад
The best way to handle it is using exceptions. If you expect a value and you get null -> that's an exception to handle. Trying to work around it is just not worth it. Exception is explicit, caught in the code, easy to test, you can write your own and make it easy to find, you can return as many different exceptions as you wish at any time and add more as codebase grows. It's just too good to use anything else.
@nickchapsas
@nickchapsas 2 года назад
Exceptions should be exceptional. I am not a fan of taking a performance hit just to have an easy way out of the application's flow. It's convinient, sure, but it's by no means good.
@javiermadueno
@javiermadueno 4 года назад
It would be nice to see a video using Option with async method
@nickchapsas
@nickchapsas 4 года назад
It would work in the exact same way. You'd just have to return Task.
@albe8479
@albe8479 3 года назад
mindblown from the elegance of this syntax. Will try to implement it at work.
@lancerhu8107
@lancerhu8107 3 года назад
Making a language more complicated to fix a easy problem.
@jeroendeclercq7580
@jeroendeclercq7580 3 года назад
The potential problem is not fixed at all. It's just another, less readable syntax to prevent it.
@nilstrieb
@nilstrieb 3 года назад
Easy problem? Null is definitly not an easy problem, there is a reason why the creator regrets it and some new languages like Rust don't have it at all.
@iamansinghrajpoot
@iamansinghrajpoot Год назад
My colleague refactored my code which returns Optional to return null 😢 My heart was broken
@UzairAli001
@UzairAli001 4 года назад
I appreciate the tutorial. I don't like the syntax that much, I prefer C# nullable over this. Of course this is my own opinion.
@nickchapsas
@nickchapsas 4 года назад
Hey Uzair, I really appreciate the comment. This is exactly why I make these videos. It doesn't need to be something that you will use but it's good to know that there is also this thing here that might be of use.
@UzairAli001
@UzairAli001 4 года назад
@@nickchapsas indeed exploring different options are definitely worth the time you never know when you might need that different approach. Keep it up 👍
@rhicanrong2494
@rhicanrong2494 4 года назад
I am looking for this too. I personally prefer using c# nullable between repository and services layers. But I think that option may serve better between services and controllers layers. It is great, Thanks for sharing.
@adriangodoy4610
@adriangodoy4610 3 года назад
Now try to convince a team to use this :(
@adriangodoy4610
@adriangodoy4610 3 года назад
I mean I like it and have been pushing to this kind of structures for years, with no results ever
@pateegutee7960
@pateegutee7960 2 года назад
How about using Null Object Pattern to avoid returning null?
@ajcroteau0928
@ajcroteau0928 3 года назад
Sounds like an overly complicated way of returning something other than null when the value your about to return is null... but c# already does this: return customer ?? NotFound; another thing is your returning JSON back to the caller, so I get the idea of option but what the caller gets back isn’t going to be strongly typed... am i missing something? Besides if your getting null reference exceptions, it just an example of a poorly coded application that lacks error handling...
@nickchapsas
@nickchapsas 3 года назад
Null coalescing has nothing to do with Option's null handling. Sure it's a fallback but it's not different than an if == null check that can be omitted if the writer isn't careful. It doesn't force you to handle it. Option forces you to acknowledge the fact that this value can be null and demands you to handle it somehow. There is no way around it. It's basically the null reference type feature of C# 8 before C# 8 became a thing. I don't think that NREs can be a metric to determin whether an application is poorly coded or not. If the value can be null then you should be forced to acknowledge it. Whether that is via the Null Refernece Types of C#8 or Option, it doens't matter.
@ajcroteau0928
@ajcroteau0928 3 года назад
@@nickchapsas i apologize, your right, my statement regarding NRE’s was a generalization... but isn’t the use of option just a way of saying if object A is null, return object B... Isn’t null coalescing doing the same thing? I do like the idea of I’m returning a customer object of null that maybe had a boolean flag of CustomersFound set to false rather than null. That to me makes sense...
@nickchapsas
@nickchapsas 3 года назад
@@ajcroteau0928 So you're right, the outcome is the same and in fact there will also be a small performance hit due to how the Option struct works. The difference is that Option doesn't give you the option (no pun intended) to not ackowledge the potential of a null. Basically you could write the same code without Option but using it guarantees, no matter what, that the developer has absolutely no way to mess it up by not handling the null option. It forces you to write more robust code.
@Gastell0
@Gastell0 2 года назад
While it seems like generally a good idea, it's simply too late? C# has null so deeply rooted that it has ridiculous amount of internal null checks where even if something is not supposed to have nulls (like this Option structure), it will be still internally routed through dozen of null checks for half of the actions...
@zondaken
@zondaken 2 года назад
Whats so different between null awareness or none awareness?
@nickchapsas
@nickchapsas 2 года назад
null awareness is optional and can be skipped. Option is a discriminated union and it has to be handled no matter what. It's safer
@zondaken
@zondaken 2 года назад
@@nickchapsas you're referring to the second delegate? Uhh true i guess. Although you can pass null to that one as well but then you did it intentionally while null awareness can be forgotten. Yeah good point, got it.
@SalihKarahancom
@SalihKarahancom 3 года назад
This is just a basic idea on controllers for web projects; don'T use null but use none 🤪. This is a very shallow perspective. You must increase your perspective and think for all system parts into its layer.
@ravikumarmistry
@ravikumarmistry 3 года назад
I am ok with null, it make the code less readable because not every body uses the library. I like to stick to language features as close as I can it make my code simple.
@r.c8756
@r.c8756 3 года назад
Well, that’s the downside of using that kind of functionality. This kind of decision should probably be best taken and enforced as a team and not just as a personal initiative
@iwan954
@iwan954 4 года назад
Rider has an option in refactoring to change signature automatically after changing implementation so you don't have to edit it manually. Very useful one, especially when you do some big refactoring.
@codex4046
@codex4046 3 года назад
Which is probably what he uses regularly, but for such a video other people might not get what is happening, doing it manually is better for explaining.
@dealstunner8317
@dealstunner8317 4 года назад
Perfect! Thanks for this video
@MoMadNU
@MoMadNU 3 года назад
I prefer to never return null and always provide a default value. In this case the default value is a real instance of a customer with the name "Not Found".
@vssrikanthgarnepudi5952
@vssrikanthgarnepudi5952 4 года назад
Hey nick can you please make a video on web api concurrency issues with an example .
@mortenbork6249
@mortenbork6249 3 года назад
Why not use the nullobject pattern? forcing you to create a "null" workflow for the object? That is much more inline with SOLID.
@jondavis4053
@jondavis4053 3 года назад
So the end result is you returned a wrapper for null-checking. More internally generated kludge in trade for easier to write and maintain syntax. At this point people might want to look at PostSharp.
@user-tk2jy8xr8b
@user-tk2jy8xr8b 2 года назад
The only issue with Option is it's not well-behaving: given `string F(bool b) => b ? "" : null; bool G(string s) => s == "";`, `false.ToSome().Map(F).Map(G)` must be equal to `false.ToSome().Map(v => F(G(v)))`, but it's not
@ronnyek4242
@ronnyek4242 2 года назад
Reminds me of rust and result types
@MrAndrei4777
@MrAndrei4777 4 года назад
Makes your code look fancier. However returning null will cause much less overhead, so the use of this tactic is rather situational, in my opinion.
@nickchapsas
@nickchapsas 4 года назад
As I explained on another comment, the performance overhead is negligible so I don't really agree with that part of the argument. In fact, it only has to save you from a single NRE to make it worth it and it definitely will, there is no question about it. I can guarantee you that there will be at least 50 different things that you can optimize on a system before you ever get to optimizing for the 35 nanoseconds that each Option will add to your system. I can however get behind not being the cup of tea of everybody especially if you haven't worked with a functional programming language before.
@MrAndrei4777
@MrAndrei4777 4 года назад
@@nickchapsas I wouldn't make any assumptions yet. The solution you provide is great, but there are many things that can be optimized in aesthetic way or performance wise. So it all depends on how much time you have and what problems you solve.
@hermit7290
@hermit7290 4 года назад
​@@MrAndrei4777 If using Option over null causes a performance issue then you shouldn't be using c# for the program. The overhead is very small but the gains in making your code more maintainable / less error prone are massive.
@user-ro3go4fm7k
@user-ro3go4fm7k 3 года назад
I don't see the need to complicate the code with these fancy thing. In the service layer, it is still necessary to check whether the object was found. And this library will not provide any benefits. And even more, if you received NRE, then something is wrong with your code, anyway you need to fix that (with or without NRE) and you will notice it obviously. Perhaps this library will make the code a little "prettier" in the controllers, but if you haven't found the entity, you may need additional logic and "Option" construction will only disfigure your code
@dariomolinari7923
@dariomolinari7923 3 года назад
Ok but Why is it better not use return NULL? which is exactly the advantage ? I'm not sure that's a good solution just to don't manage a if condition. In ajax you could manage the null return condition of a controller very easy
@zenitkov
@zenitkov 3 года назад
From a client perspective often you don't know whether the object can be null or not, so it forces you to either check the implementation (which might change internally anyway) or make an additional check. Now, when you have null references setup as errors and with something like Optional you know exactly in the contract if it can be empty.
@johnnybravo8281
@johnnybravo8281 3 года назад
Zenit Kovacevic Every reference Type can always be null, there is no need to check the implementation.
@AngusMcIntyre
@AngusMcIntyre 3 года назад
We should really all be writing f# for our application and web tiers.
@errrzarrr
@errrzarrr 3 года назад
I like the approach
@BMXcrew98
@BMXcrew98 4 года назад
Well, if you dont handle nothing as a return value, you get the Same error with Null. So i dont Unterstand Why you want to delete it
@nickchapsas
@nickchapsas 4 года назад
This is wrong. You cannot not handle None when you’re using Option. The code won’t compile. This is the difference, that you NEED to handle None or else the code won’t even build. There are no NREs
Далее
What is Span in C# and why you should be using it
15:15
😂😂
00:16
Просмотров 856 тыс.
What are record types in C# and how they ACTUALLY work
15:36
Manage Nulls Like a Boss and Never Fail!
21:43
Просмотров 13 тыс.
The Right Way to Check for Null in C#
9:35
Просмотров 97 тыс.
Naming Things in Code
7:25
Просмотров 2,1 млн
Don’t Use the Wrong LINQ Methods
12:42
Просмотров 46 тыс.