The Right Way to Check for Null in C#
HTML-код
- Опубликовано: 25 авг 2024
- Check out my courses: dometrain.com
Become a Patreon and get source code access: / nickchapsas
Hello, everybody, I'm Nick, and in this video, we will take a look at the right way to check for null in C#. C# has been around for a long time and the process of checking for null has evolved as the language itself has evolved.
Workshops: bit.ly/nickwor...
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...
Keep coding merch: keepcoding.shop
#csharp #dotnet
And for those wondering, both null-coalescing operators (??= and ??) and the ?. operator will be compiled to the "is null" version if the compiler detects that the operator is overloaded
That's why the Unity code analyzer complains about using null-coalescing operators.
Why not doing this: if(!(user is object)) : this the more secure way to check for null references even if the == operator is overreriting
@@tottiinfowhy would you choose that over if(user is null)
Let's be real, if the == operator is overriden in such a way that it can no longer check for null then the correct response is not to adjust your coding style, but to crucify the person wrote the override.
this
agree, it reminds me of colleagues arguing back in 2014, that having IEnumerable/IReadOnlyCollection return type is not enough and you should always iterate-yield the whole collection or .ToList() clone it before returning, since the consumer of your interface can downcast the returned reference back to the original List/array and then modify the original instance.. I think we should not upfront-compensate for hypothetical retard-alert situations, or use them as reasoning.
Still, the "is null" syntax looks quite neat
@@Smakenzi lmao well you can also use reflection to access private methods in java for example.
Your job is to prevent the users from shooting themselves in the foot accidentally, not from shooting themselves in the foot on purpose.
Cloning an interface everything you return it is wild, you should not do that.
lmao this honestly
Seriously, this video was completely pointless. Content for the sake of creating content.
I've been using the "is null" for a while now purely because I think the syntax looks better and more readable (when you read the code in your head you're essentially translating "user == null" to "user is null" anyway), the fact you can't ever face issues with the equality operators being overridden is a nice bonus though
Awesome.
This 👆
I hate how similar it looks to the type checking "is".
Same for me, but is a bit annoying that Copilot still often suggests '== null' and I have to change it manually
I'm not going to lose any sleep over my code having `== null`. In over twenty years of programming, I've never seen the `==` operator overridden.
^^^ this
More importantly, if anyone overload it and decided that particular value is equal to null then I guess we should treat it as null
I've seen several overrides to == and done them myself, particularly for implementing value equality on DB record key fields, but I've never once seen null overridden to have any meaning other than the expected meaning. Still, I'm slowly converting all my == null checks just to be sure that when I want to be sure I'm doing a ref check that that's what I'm actually getting.
@@RobinHood70 obviously my experience doesn't apply to everyone but, having contracted at almost 20 companies, I'd say my experience isn't unusual.
@@stevenbey I didn't mean to imply that it was, just that overriding equals does happen. It obviously depends on what kind of work you do. I used to do a lot of database work, so value equality was a pretty common thing for me to write.
Unity dev here. I like that you mentioned the operator overloading in Unity, but it’s applicable only on object derived from UnityEngine.Object. On everything else and all your standard managed objects, you’re good to go with the « is » and « is not » operators. Good video though!
What I like most about your videos Nick, is that you explain the "why" behind it and I often learn just as much by the behind the scenes things as I do the intended topic. For instance, a while ago I picked up on your video about overloading default methods like !=, == etc. Thanks for all your videos!
I pretty much like 'is' and 'is not', it is pretty readable.
Python style
I do the same… that ==, != I just hate it!
I much prefer it which I why I always use it to check for null it’s easier to read and it avoids unwanted operator overloads from messing up the check
@@stefano_schmidt SQL style
@@UweKeimyeah its more like SQL
I've never bought into the idea that we need to guard against someone overloading the == operator incorrectly.
Don't get me wrong.. the "is null" operator is fine but the idea that you would ever need to assume an operator overload is implemented to do the opposite of its intention is just insane.
We don't go around calling the `Add` method expecting it to subtract. Nor should we expect == to not equal.
I get you but It's actually deeper than that. Consider you are using NRTs in your own code and you define a type as nullable. What do you really when to check when you write "== null"? I would be very surprised if what you intend to do is check the reference of the type being null. But if you won't use "is null" and there is an overloaded operator then you are at the mercy of said operator, which can be dangerous. That's what "is null" saves you from,
@@nickchapsas I don't normally disagree with but this time I really do. You can't (or rather shouldn't) just assume that code written by someone else is wrong. If someone is crazy enough to overload the == operator to change how nulls are compared they're doing that for a reason. Whenever you work in a team you're "at the mercy" of other people's code. Also personally I hate the syntax of "something is null", it's too wordy for me and looks too much like Visual Basic.
@@nickchapsas I've been coding for 30 years... about 20 of them in C# so maybe I've just got a good understanding of how things work. That said, I also work on teams with less experienced coders and I just don't see this as being a real source of actual bugs. Most of the time when this topic comes up it only exists in contrived examples (much like the one in your video).
I must admit the "is null" syntax looks better but at the same time it's another rule to learn. There's decades of code out there using == operators for null checks so at the very least new coders still need to understand both for quite some time. More importantly, there's now a new source of bugs when refactoring old legacy == operators to "is null" checks because it's possible to break the original intention of the code if operator overloads where actually used to solve a real world problem.
"is null" might very well be objectively better in many ways. I'm just playing devil's advocate and pointing out that there's always a trade off.
Fully agree. It's crazy to me how this has been so easily accepted as the "default" now. My team tried to introduce it to our codebase but I flat out rejected it and suggested we should keep on using the usual operators. The only place this might make sense is when you actually need it for chaining pattern matching.
Also, "is" and "is not" are not more readable to me. They're also not symmetric, unlike "==" and "!=".
We prepared a gallows in the company backyard for developers overloading standard operators. It's considered an important part of our effort to enforce the coding guidelines.
If you find someone overwriting == the correct course of action is not to go along with what they are doing but instead to beat some sense into them. Overwriting == shouldn't be done lightly and if you must do it it should not impact existing code.
For a first offense you should use a rod no bigger in diameter than your thumb. For a second offense feel free to introduce them to your grandpappy's walking stick, "old hickory". Third offenses aren't an issue. Kidding aside I agree, it's rare that operator overloading is actually needed and as it's hidden logic you can't see by looking at the code it often just leads to late night debugging sessions. So use with great care and only if you have a legit need. In 30 years of C++ / C# coding I don't remember ever having a need.
totally agree, I'd raise hell if I saw that in a PR. that being said, how do you control/prevent overwriting == in nuget packages?
@@shaicohen2 Luckily you can't override == for primitive types and overloaded operators are limited to the type they are defined on. This means that if == is overloaded in a nuget package it would only affect types defined in that package. The only way I can think of that operator overloads, in a nuget package, could cause harm is, if you had a nuget package installed and you upgrade to a new version where the == operator has been overloaded in a way that is different from what it was before.
I have been coding for over 30 years and as a matter of principle, I never allow overloading of basic operators within the teams I work in.
I often override Equals for new immutable classes and structs. If I override equals, then I always override == so it works the same way. Not doing so would be a trap.
That's also how SQL server queries check for null values. So it is actually convenient to use the same syntax null check in server back-end and in database.
Things I learn from this video:
1. Operator overloading is really good in theory, but very bad in practice
2. C# is very complicated language, a simple thing like null check can be done in 10 different ways.
I like the "is null" because it's the same way you do it in SQL. And everyone knows SQL is the best programming language of all time
Can we please start hating this guy for such statement?
In SQL i check for Null by Not (a=a)
Great feature and a great video.
In fact I've actually written about "x is object" back in 2019 in a blog post I've named "The perfect non-null test". In c# 9 when they've added the not keyword it got that much better with "x is not null" - but still learned something new about how it actually works in lower c#, so thanks!
Personally, I enjoy using the maybe/option monad. It keeps my code clean from null checks, ensures that the caller handles both scenarios of when there is and isn't a result and it can handle any type, not relying on nullable being implemented.
if == operator is overwritten and does not handle (x == null) case then it's either a bug or intended behavior
Ha, but that's actually the responsibility of the underlying type, not yours. If you're using NRTs for example and something is nullable because you defined it as such, then == automatically implies a reference check. That's why "is" is what you would want to use in this situation.
I love this and I didn't knew about the weird "is not null". I wish C# would get the balls to say "okay, this will have breaking changes, we're removing all the useless stuff now" at least once a decade.
Because now the == operator is now “useless stuff”, makes total sense
Yes. the language design team is actually working on something akin to rust editions now
I actually use "==" and "!=" for simple null checks its just personal preference because I like to keep the "is", "is nor" "or" and "and" stuff exklusive for more complex pattern matching since that is the area it acutally helps with readability
I use the R#/Rider setting under code inspections to Colour Identifiers, which adds a bunch of semantic options for how to colour the code, which includes being able to chose different colours for normal operators vs overloaded operators.
This is a cool idea, that should be on by default. JetBrains take notes!
That said I have never seen == to be a source of a bug, nobody is crazy enough to change the null check behavior unless it's absolutely necessary. Unlike implicit operators that can create super unintuitive ambiguity problems.
@@the-niker note that R#/Rider's inline type hints show an indicator wherever there is an implicit operator in use.
I set them to toggle on hold of ctrl, and show/hide on double press of ctrl, so I can easily control when I see them.
Anyone complaining about the verbosity of "is not null" is probably doing something strange anyway. When do you WANT something to be null? The normal way to code defensively is to do a null check warn, tidy and drop out if its null. You can do that with "if (x is null) return;" and the rest is implicitly not null and you save on indentation and compliexity.
2:40 The pain of using Unity3D's ages old C# is REAL. It seems that C# in Unity3D was trapped in a time cage that only move forward in a REALLY slow speed. It's kinda like Java 8 :-(
Well, we are at C# 9 right now, which adds a lot. We are missing some conveniences from C# 10 like file scoped namespaces but I think C# 11 is not as big of a change as the previous versions.
I will overload equality operators when I'm not necessarily wanting to resolve whether the reference is the same but rather based on property values, like an object with a DateTime field. I will overload so that the objects are checked for null (via 'is') first then whether the DT field is the same. If they are, the objects are "equal". I do the same for objects that have an ID field as two objects cannot have the same ID without being equal.
You should formulate if statements positive for no double negation.
Anyone who tries to overload the == operator in my code base has to walk the plank
I'm quite a fan of `switch(param) {case null: ... case TypeA a: ... case TypeB b: ... }`
Also, what is it with `if(param is var a) { ... }` and `if(param is { } a) { ... }` having different behaviour? if you're not aware, the former accepts nulls, but only if you don't put param's actual type in there.
But geez... Overloading static operators like that is insane... why would you even do that?
I'm quite happy to stick primarily to `==` and `!=`, but then I've also not worked on any code that overloaded static operators, not even to just forward them to Equals() and CompareTo().
Even with the IEqualityOperators and IComparisonOperators interfaces in .NET 7 (if we ever more on), I don't see that changing...
2:25 if you want the technical reason, the Equals function is non-static, and with the variable being a null, the runtime cannot access the vtable (this is where the NRE occurred) to find the correct Equals function.
By using railway or functional programming, you shouldn't worry about null values as long as you are consistent with your conventions, for e.g. using the following records Result.Success(T value) and Result.Failure(IFailure failure) with a boolean property called IsSuccess. It tends to be more business oriented, rather than dealing with framework sugar syntax.
Agree, "is null" both reads much better and is the better option from an implementation point of view.
Ive been using all these features not because I knew about it but because Resharper always suggested me to change my conditions according to these new ways an di kinda loved it :D
I always use == and != because of a habit and I never overload equality operators nowadays, let alone null equality. Personally I think that being allowed to modify what == means in such a hidden way was a design mistake. It looks cool until it bites you. A much better option IMHO is to generate (with Resharper) or implement by hand some EqualityComparer for your classes and give them a meaningful name. Like IdComparer or ValueComparer for example. So you get the special behavior only when you need it and that’s clear to everybody reading your code. No surprises.
Then ok: is/is not looks better 😅
BTW, great channel Nick!
Been using "is" and "is not" for some time now. I like how readable they are.
i like the new features, thanks for bringing them to our attention in a easily digestible way
TBH I haven't seen operator override for years now - it's really exotic tool that can be used only in domain objects and you have to have really good reason to override it, where most null checks are performed od DTOs in layers above.
Eh.... yes you can override the == operator and !=.... but really how often do you do that? Sure a 3rd party library may do it and hide it from you.... but really? I'm sure this would be needed in some places or some use cases. But for the majority, eh ill keep using == and have zeros problems like i've been doing for 20 years in c#.
1. Operators are not dangerous.
2. Checking with == is perfectly fine.
If you overload == operator then you should have a very good reason to do and you should use it accordingly. I've been programming for more almost 15 years and I don't remember a single case someone overloaded == operator and my null check was broken.
Do not misinform new developers just to get more views.
Never thought about it this deeply actually. Good perspective check for me.
I use a naming convention of a "maybe" prefix for my nullable variables. I then use the form: if (maybeValue is not { } value), which usually then is the exceptional case (return an error message or something), and then the normal case can continue on with the known non-null value variable.
Even if you overload the equals operators/methods, you have to ensure the outcome is externally identical to all other equality checks. For example you have to ensure that "yourClass == null" is false if an instance exists, otherwise true, even if both sides are null. ReferenceEquals is useful for the part where you implement the equality check internally, as to ensure you don't just use your own equality methods reciprocally.
Also because you *can* overload the equality operator, it means it is preferable to use "==" because it is properly doing the equality check logic. It is overloaded BECAUSE other means are lackluster.
I don't like his thought of "someone could have overloaded it poorly". Well, yea, null check might not work right. Hell, lots of code might not work right if someone wrote poor code that you are making your code dependent on.
@@darknessgp1 Exactly. Poorly written code can be a menace in many ways, and can ruin all sorts of conventions and reasonable expectations.
Too much overstatement on operator overloads. These should just be implemented correctly by their respective authors, if they are even used. I continue to use != null
Learn something new from this video. Also, my policy is to never use operator overload and in most companies I worked for operator overload is prohibited.
A good implementation of custom operator== should equal two nulls so I would say just use == like before.
Assuming a custom operator has a good implementation is just asking for trouble.
Did you know for instance that (myObject == null) can actually throw a freaking exception in Unity?
@@Falanwe The idea that you would ever need assume any code has a bad implementation is pretty insane.
Think about it. If code is not working as we expect it either means we've found a bug OR we don't actually understand why it works that way in the first place.
The correct action is to fix the bug, read the documentation or implement a workaround NOT assume every possible implementation of that that code forever into the future as possibly wrong.
@@ExpensivePizzaThat's the right way to do it if you have control over that code. You don't always have it. In the cse of the Unity overload you absolutely don't.
@@Falanwe Then it's a bad implementation. I think introducing is null was a bad decision, just cast to object? in the case where you need real identity equality.
@@Falanwe Unity has something like a million developers using it. I'm one of them.
No doubt Unity has some confusing behavior's but I find it very hard to believe the Unity team didn't think about the pros and cons of their implementation.
In other words, Unity is working exactly the way it was designed. It's well documented and tested. So in that case I would say it's about learning not fixing.
Thanks for the vid, it's been a burning question for me lately which way is best.
This is ridiculous.
If I or any of my colleagues or 3rd party tools overloaded == to return false for null checks with nulls, my smallest problem is the actual "wrong" null checks and actually the mess I have I have in my project (and the dumb shit people that work\ed on this project).
That said, is null is indeed a nice way to write, that reminds python's is None.
A little extra feature is that null can be used to check for null pointers as well. It took me months to figure out that I can just use
‘ptr == null’
instead of
‘ptr == (T*)IntPtr.Zero’.
using "is null" doesn't work in LINQ queries since expression trees may not contain an "is" pattern-matching operator. Result is that collection.Where(x => x.Property is null) throws a design-time error.
Wow! I didn't have a clue about his... Thank you!
The "is null" syntax makes me think of SQL and that triggers some PTSD.
I laughed when you mentioned VB...when I was working with NULLs in VB way back I saw many different ways of writing it, the best being: If Not item Is Nothing
Recursive pattern, used in 'is {}', is only available from C# 8. Since it's syntactical sugar, you can change the language version in your csproj file without changing the .NET version with `8.0`. This worked for my .NET Standards 2 project
As always an fantastic video! Could you do a video where you explain the different steps how C# code will be compile: Lowered, IL ... etc.? That would be awesome!
Thanks for pattern matching examples.
@nickchapsas
I have checked the below
var x = new Test();
x = null;
if (x.Email is null )
{
return BadRequest();
}
and this throw an exception becuase x is null and if its converted to (x?.Email is null)
should not throw an exception .
while the below didnot throw exception :
if (x is { Email: null })
{
return BadRequest();
}
I learned object checking method thanks to resharper. I'm always using is and is not null way. It's more readable for me.
I'll just bookmark this video for my next code review
Thanks for the video! I'm a bit confused about the Unity part - which classes exactly have overridden the == operator? Some Unity's own classes? If I'm using only my own classes in Unity, using "is null" should be safe, right?
Yes, you can use pattern matching and "is null" for your own classes as long as they do not inherit from any Unity class (MonoBehavior, ScriptableObject, etc). In Unity, checking for null (with ==) does not check if the C# reference is null, it checks if the Object has been destroyed in the scene. So if you do if player == null you are checking if the player object exists in the scene, but with if player is null you check if the C# reference is null, which is not very helpful as it usually is almost never null. In 99% of cases you want to use == null in Unity.
@@marcusotter Thanks! Looks like I wasn't so reliant on Unity's own shenanigans in scenarios like in your example. If I want to check if a reference is null, I literally always means to check whether the reference points to a null object or not. For checking whether a gameobject has been destroyed I would Destroy() the object and in addition set all references to it as null (like in the player example In these cases I like to create a layer of abstraction). In this case, sounds like using "is null" should be safe for be both for my own and Unity's classes, as long as checking for null reference is literally what I'm after.
Everyone saying "I'm not gonna change how I write code because no one would ever intentionally write the == override to do crazy things!"
Yeah, I'll grant that we should assume that no one will ever do that _intentionally_.
But there is such a thing as writing code to do things unintentionally, and we've all run into it. Hell, we've all done it. I did it probably a couple times today. They're called bugs. And if you tell me the code you write doesn't have any bugs, I won't believe you. And I don't think you believe you either.
Let's say you have a class where if the ID property is equal, they should be considered equal as well. But if the ID property is null, then they're different, even if ID is null on both. Because it's for an ORM, and it's just two rows that haven't been inserted yet, you know? Unless the reference is equal, then it is.
You're tired, it's Thursday evening, and you write this override to handle checking the ID property as well as reference checking.
public static bool operator ==(MyClass? A, MyClass? B)
{
if (A?.ID == null || B?.ID == null) return false;
return ReferenceEquals(A, B) || A.ID == B.ID;
}
Console.WriteLine(A == null); // false
Console.WriteLine(A); // null
But why? There's two answers to that question.
First, the wrong answer: Because the null conditional operator returned false when either A or B is null. So you get false just because you're comparing against null.
Second, the right answer: Because you're still using the bad way to check for null even though you know better.
Never trust any code, especially your own.
And if someone has overridden the equality operator he is mayme doing this on purpose. By using "is null" you might miss this case and trying to work with an falsy object?
Incorrect because the responsibility can be shared. Consider that you define the type as nullable so you control the nullability and the logic. In that case is null is a must
Now, lets talk about the use cases of the goto statement in C#
Shouldn't be a issue if your team follow coding standards. In my team code that overrides == operator would never pass code review. If we want custom comparison we add methods and then use that method.
This is were I differ from your explanation, if something is overridden it should be used.
You can use "is" with you cannot overload :)
Thanks, Nick!
👍
@Nick - thanks for the video. can you overload object's null check (== null ) operator? also how does it impact ?? null coalescing operator?
It doesn’t work then!
Null-coalescing operator literally doesn’t work in Unity and that’s one of the reasons why I hate it!
Only if the is operators could theoretically also be overloaded 😢
Yeah. we have been using "is null" and "is not null". good to see C# is coming a long way..
I tried if (user.Child.Name is not null) when user is null and it throws System.NullReferenceException. It looks like it does not translate into if (user?.Child?.Name is not null)
I wish you could just do `if (user?)` { ... }. That would be consistent with the ?. operator. It'd just be syntactic sugar but still.
With if(null == item) you will also get everytime the right null check. Because you can't override the == of null. The operater == will always take the left sight oft the operator to check the equal.
As you can see in the video, you can totally override it
Hi Nick: What you failed to add in your video is why "Unit Testing?" If you had your application properly covered with unit tests then you could easily do a search for "== null" and simply do a replace with "is not null" and your unit tests would immediately pick up if you had a problem with your code. One of the biggest complaints I have with code is that top level code that isn't easily readable and understandable by no developers. I have seen in OnClick methods that are over 20,000 lines long where the code should read something like:
DoThis();
DoThat();
if (Person.IsDoing == Activity.FunkyChicken)
ShootThem(Person);
DoThis() and DoThat() are easily understandable by anybody but I can very easily write unit tests for these types of methods. I can run my unit tests locally and my unit tests will fail if the code isn't written to the current standard.
My favorite way is
If(user is User notNullUser)
{
//Use notNullUser
}
I really like this approach, because i think its the safest(i think it should be safe even in a multithread enviroment but not sure about it), but also great in the case of the last example, when you need a Child of the class.
So if you want to use user.Name.FullName, in this case you can do
If(user?.Name?.FullName is string userFullName)
{
//Use UserFullName variable
//instead of repetitively
//user.Name.FullName
}
Yeah, pattern matching like that is phenomenally ergonomic, I love it
I once tried to do exactly that the lazy way by writing: `If(user is var notNullUser) { ... }`.
But for some reason using 'var' makes the test always pass, even with null... 🥴
At least that experience taught me about `if(user is {} notNullUser) { ... }`.
@@billy65bobHmm using {} instead of direct type sounds interesting did not know its possible, thanks, but still i prefer to write out the type everywhere its not obvious as it helps later on when i read the code, easier to see what's going on when the type is directly visible.
Also i wonder how 'var' is handed might check it out...
I've been using the CSharpIsNullAnalyzer analyzer in my code for a while to pick up cases where I've not used the `is null` pattern match - was using ReferenceEquals before in a few places to be explicit about what comparison I wanted, but hated how that looked when reading the code
I didn't know about that null check with pattern matching
This is a pretty elegant solution, but could you also have a convention where your object(s) are always returned in a list so you could just check the length? Kinda like ol' jQuery lol
"is null" reminds me of all the tsql i used to have to write. i also remember using IsNothing() in VB back in the day. switching to "is null" in c# is going to be difficult. it just feels foreign to c# to me
is null does not work with Unity objects when they have been destroyed
This does so not make sense when you watch the Code Cop series. In Code Cop you say things like "don't do this all the time, context is important" and here in this video you're all about "do the is null period" even though overloading the operator is a situation you will never encounter. Unless you join a already established project, but then this advice has to be tailored for those cases. Otherwise you will never have that situation, unless you have a project and some nitwit comes over and overrides one of the most used default behaviours... again, very rare.
I'm fine using is null. But what kind of maniac would override the equals operator to have the null check return another value. In all my years I have never had any one on my team or came across any NuGet packages that did this.
Personally, I avoid using null checks all together, for as long as it is possible.
The idea is that if you need a null check, you are in an invalid state and therefore your code is doing something it shouldn't; the code breaks, allowing you to rethink why it just did, allowing you to find the real cause as to why the data is in said state.
That's not to say that I avoid null checks completely, but rather use them extremely sparingly once I'm sure there is no other way.
if some one overloads the equals operator on a class in a way, that simple null checks don't work any more, then i chop their hands of.
hey there! important you mentioned "unity" game engine about nullable things . thanks
Re your q about feature creep, yes e.g. new deconstruction syntax and indices and ranges, I guess to attract the python crowd. Also complicated as you have things like records and have to remember if record structs properties are writable. Also new 'with' keyword and immutability etc. The null story isn't good, elvis operator, null coelescing and the assignment desparately needs Rusts approach with Option. A real smörgåsbord language.
At 2 minutes in why is Rider highlighting the 'if' ? I just started using rider on my macbook and am confused why I get so many squiggly's and warnings for stuff I don't in visual studio
Calling the equals operator potentially dangerous because of the possibility of it being overriden is bogus.
Might as well go gambling due to the life changing possibility of winning the jackpot
This makes me think that Java's decision to not support operator overloading is a good thing. My version of checking not null was " if (!(obj is null))"
Hard disagree. Just because a tool can be abused doesn't mean it's a bad tool.
Ugh... Now I have a headache and a pile of code to review. Thanks for sharing!
The issue here is not == but why you would overload == its a code smell. same as referenceEquals its harder to read in a complex codebase. A codebase should be simple for new developers to get started, any modification that changes the norm is a code smell. If you want custom == behaviour make a library/core that allows for custom operators in specific domain issues.
Agree, this seems like such a bizarre reason to switch operators
Another way to check if it is not null like "is {}" can be "is object".
That is correct, which is ultimately what "is {}" means
@@nickchapsas "is object" and "is {}" is different thing, because in you can have "if (s is {} x)" - s have type T?, x have type T, not an object type.
"is {}" pattern is more powerfull.
Also, you didn't say a word abount mass null checking, .Where(x => x is not null) can be .OfType(), because OfType internally filters null values.
I am from the future and c# and vb are indistinguishable.
You bringing up Unity and saying to stick to == there is really interesting, because for me it's exactly the other way around.
Often, your null check is just there because you want to know if something was initialized already, and the == in Unity will not let you do it if you're not on the main thread for Unity objects. Having (something == null) throw an exception is really a bad experience and justifies using other syntaxes without the issue.
Well that's because any code interacting with the Unity API needs to run on the main thread as you say. Even if "someObject is null" may return false using it's transform may throw an exception. A common work around I've seen in some plugin is a "ContinueOnMainThread" extension method which works on async Tasks
Hi, Nick, thanks for the great advice. Is performance affected by this method ?
Not anymore. It's used to be
Thanks for the vid, I'm still unsure tho, is checking with '?' the same as 'is null' ?
My 2 cents:
1. For `if (user is not null)` if your compiler version does not yet support the `not` keyword yet, you can write `if (!(user is null))`
2. How does one write a `is null` on a predicate expression tree? At least, my compiler does not support it. I will try `ReferenceEquals` or a cast to `(object?)` the next time I will be next the compiler.
Please do a video on ConfigureAwait().
Interesting info. But, while I use the 'is null' and 'is not null' checks, I do it for readability.
In spite of having worked with some extremely bad code over the years, never have I come across code so bad that an == override is written poorly enough to break a null check.
Being old and being bad is not mutually exclusive.
what if I tell you that after a few years working like 20% of my time with C# I've never seen anyone overwriting == or !=, didn't even know it was possible...
Not often done with class types, but very often with structs.
Also, records overload the == operator, so
Debug.Assert(new User("Bob") == new User("Bob"));
record User( string Name );
what is the difference between null and default?
null is always null but default can be null if the type is nullable but also not null if the value is not nullable. For example the default of int is 0 but the default of int? is null
Let the compiler deal with it. Don't turn a null check into computer science. Keep it as simple and clear as possible.
One interesting part which is missing imho is the behavior of nullable structs with is.
Because however structs can never be null AND is does not call Equals internally, default(int?) is null returns true.
Nullables are a strange thing because the CLI actually chooses the Struct or null depending on your usage in IL code.
int? = 1 will be an int, but int? = null will be a null ref. Nullable is just a lie as far as I know :D
Another interesting part is the behavior with ref values if you use Unsafe.NullRef you can actually create a struct with a null value.
Accessing it will lead to nullref exceptions.
What are your thoughts on using "is object" when doing null checks?
It's the same as "is {}". I think that both of them don't clearly show intent (that it is a null check) to the reader.
A benefit of 'is not null' is that it emits a compile error if you try to null check a value type. 'is object' only emits 'this is always true'.
I've been using "is null" and "is not null" for a while and was aware of operator overridden issue as well. you may say how did you figured it out earlier: well yes! I came to know while going through .NET PRs 😃
What about default? isn't that the new way of checking reference types?
Did you just say C# is an "old" language? I've worked with it since before it was released and it was called COOL. How can this be? I'm not old oh, wait...