C
C#ā€¢11mo ago
LazyGuard

āœ… Nulls in C#

Hi, Consider the following Ruby Code
67 Replies
LazyGuard
LazyGuardā€¢11mo ago
This will throws some exception that is similar to NullReferenceException
LazyGuard
LazyGuardā€¢11mo ago
The reason why is that in line 16, the find method is returning a Nil (equivalent to null), passing it to the Subscription class and then in the create! method, we are acessing the name attribute on it (person.name) and that is what throwing the exception The line that introcued the Nil (i.e. line 16) is not in the stack trace !
x0rld
x0rldā€¢11mo ago
what's your point ? it's not c#
LazyGuard
LazyGuardā€¢11mo ago
yeah it's not C#, coming from a Ruby background I am wondering whether C# fully eliminates these kind of problems I've tried to play with it a little bit the thing is that if the compiler detects something can be null, the type is Nullable, and thus we cannot call whatever method on it is there other cases where we fall into the same problem as ruby ?
x0rld
x0rldā€¢11mo ago
the compiler detect if that can be nullable but you still can use it it's not a compiler error
Thinker
Thinkerā€¢11mo ago
C# still has a NullReferenceException exception which is thrown if you try to access anything on null. There are technically no mechanisms which prevent you from doing this, although in more recently language versions you can enable a set of warnings about null.
MODiX
MODiXā€¢11mo ago
Thinker
REPL Result: Failure
string s = null;
s.Length
string s = null;
s.Length
Exception: NullReferenceException
- Object reference not set to an instance of an object.
- Object reference not set to an instance of an object.
Compile: 430.573ms | Execution: 54.339ms | React with āŒ to remove this embed.
Thinker
Thinkerā€¢11mo ago
So the answer is that C# doesn't eliminate null problems but you can be pretty safe
LazyGuard
LazyGuardā€¢11mo ago
yeah but at least I am getting a warning from the compiler telling me that I am possibly derefrencing a null refrence right ? Is the compiler always warning about such cases ?
Thinker
Thinkerā€¢11mo ago
Yeah, and you can even turn that into an error if you want to Usually, yes, if you annotate your code correctly. There are cases however when the compiler is either overly restrictive or lacks sufficient information, so it can be wrong sometimes.
Pobiega
Pobiegaā€¢11mo ago
And it only works for libraries that were written with nullable annotations So if using an older library, that might not be the case
Thinker
Thinkerā€¢11mo ago
And you can turn it off completely
x0rld
x0rldā€¢11mo ago
that remind me of my project in webform where the compiler put "that can't be null" everwhere on nullcheck cause there is 0 nullable
Thinker
Thinkerā€¢11mo ago
yeah I was using ANTLR4 a while back and that has no nullable annotations yet everything can and usually is null
LazyGuard
LazyGuardā€¢11mo ago
you mean this <Nullable>enable</Nullable> ?
Pobiega
Pobiegaā€¢11mo ago
Thats one way of doing it, yes but even with that, you still need to annotate your types ie, returning T? instead of T from a method that can return null accepting T? instead of T if your method can accept null values etc etc etc
LazyGuard
LazyGuardā€¢11mo ago
hum meaning that if in a method if I use return type T whereas in reality it can be T? that would not issue a compiler error, right ?
Pobiega
Pobiegaā€¢11mo ago
? Yes, it certainly would If you mark it as T, but you return a T? or null, that will be warnings
LazyGuard
LazyGuardā€¢11mo ago
yup but that warning will be located in that method. Everywhere else where the method is used, I will not get warning about dealing with a null return right ?
Pobiega
Pobiegaā€¢11mo ago
uhm, no
LazyGuard
LazyGuardā€¢11mo ago
So there is a risk of having a NullRefException with no warnings what so ever
Pobiega
Pobiegaā€¢11mo ago
thats not how it works or well, sure, if you ignore that warning because if that method comes from a file/assembly that is flagged as #nullable enable or <Nullable>enable</Nullable>, its assumed that it will never return null because thats what the type system says about it this only happens if you lie to the compiler and ignore the warning thou and its not really reasonable to expect the compiler to handle that, is it?
Pobiega
Pobiegaā€¢11mo ago
LazyGuard
LazyGuardā€¢11mo ago
haha what a coincidence, I was writing a code about persons too
Pobiega
Pobiegaā€¢11mo ago
for example, this method. in the first picture, we get a warning because it promises to return a Person, but we explicitly return null. that triggers the warning
LazyGuard
LazyGuardā€¢11mo ago
here it is
Pobiega
Pobiegaā€¢11mo ago
in the second image we supress the warning by saying "trust me, this value is never null" aka the null-forgiving operator
x0rld
x0rldā€¢11mo ago
why you allow age to be null ?
Pobiega
Pobiegaā€¢11mo ago
yeah that code screams bad design you should not take in a nullable parameter if your code cant handle the null taking in T? value then throwing when value is null is bad
LazyGuard
LazyGuardā€¢11mo ago
it's jsut a toy example here, to show that the warning is only located in the Create static method
Pobiega
Pobiegaā€¢11mo ago
right, because that method is breaking the contract it promises to return a person but in reality it can return null
LazyGuard
LazyGuardā€¢11mo ago
and since I am lying to the compiler and telling that it returns Person wehars in reality it' s Person?, it doesn' t help me later
Pobiega
Pobiegaā€¢11mo ago
thats the same behaviour you get if you disable nullable reference types correct this is why in "real" code, its very common to elevate these warnings to errors
LazyGuard
LazyGuardā€¢11mo ago
wheras if I am honest
Pobiega
Pobiegaā€¢11mo ago
exactly
LazyGuard
LazyGuardā€¢11mo ago
the compiler will help me prevent the nullRefExceptions with warnings
Pobiega
Pobiegaā€¢11mo ago
you've discovered why this exists :p as a fun experiment, try implementing this in a language that truly doesnt have null
x0rld
x0rldā€¢11mo ago
is None allowed ? kappa
Pobiega
Pobiegaā€¢11mo ago
Option<T> is absolutely fine but trying to return None from a method that returns T... that aint gonna work chief C# has had null for 20 years, nullable reference types are just a way to help us work with it better. its not a true "removal" of null if C# was re-designed from scratch today, we probably wouldn't have null
LazyGuard
LazyGuardā€¢11mo ago
what language do you suggest ?
Pobiega
Pobiegaā€¢11mo ago
Rust
LazyGuard
LazyGuardā€¢11mo ago
Okay, so to summary all the things, The nullable reference type does not remove the NullRefrenceException, it's just a way to help the compiler so that it can prevent you where we may have such issues. The limits is that : 1. This assumes that you correctly help the compiler 2. The Nullable option is enabled How the 2. is related to old libs. If I use an old lib that does not have the Nullables, i will not get the warnigs right ?
Pobiega
Pobiegaā€¢11mo ago
correct
LazyGuard
LazyGuardā€¢11mo ago
because nullable was introuced in C#8
Pobiega
Pobiegaā€¢11mo ago
or hm I think thats how it works its either that or it assumes all types are T? since thats closer to the truth
Thinker
Thinkerā€¢11mo ago
That would be ridiculously annoying though, it assumes nothing is nullable
Pobiega
Pobiegaā€¢11mo ago
easy enough to test make two libs, one with nullable on one with off
LazyGuard
LazyGuardā€¢11mo ago
What I am struggeling to understand, is that I have a bad mental model for what a library exactly is šŸ˜¦
Pobiega
Pobiegaā€¢11mo ago
an assembly
Thinker
Thinkerā€¢11mo ago
Have you ever installed a Nuget package?
LazyGuard
LazyGuardā€¢11mo ago
Even though I am using an external lib, It's not my config of my main project (nullable enabled or not) that gets taken into account I did, but I didn't look under the hood how it works
x0rld
x0rldā€¢11mo ago
when you create a project you can choose library instead of console application
LazyGuard
LazyGuardā€¢11mo ago
that means it's already compiled ? so when I compile my project, it doesn' t get recompiled right ?
Pobiega
Pobiegaā€¢11mo ago
wat
Thinker
Thinkerā€¢11mo ago
wat
Pobiega
Pobiegaā€¢11mo ago
wat
Thinker
Thinkerā€¢11mo ago
When you compile your project, it gets turned into a DLL file. When you recompile, that DLL is regenerated.
LazyGuard
LazyGuardā€¢11mo ago
ok, but what about the lib, if a lib is an assembley it means that it's already compiled when I import it as a nuget
Thinker
Thinkerā€¢11mo ago
yep
Pobiega
Pobiegaā€¢11mo ago
Thinker
Thinkerā€¢11mo ago
Installing a Nuget package is basically downloading a glorified DLL file containing code which the .NET runtime understands.
Pobiega
Pobiegaā€¢11mo ago
Pobiega
Pobiegaā€¢11mo ago
no warnings but will throw NRE so when using libraries where its disabled, you assume no nulls very dangerous
x0rld
x0rldā€¢11mo ago
I hope no one will enable that to publish a library xD
Pobiega
Pobiegaā€¢11mo ago
no but there might be legacy libraries
LazyGuard
LazyGuardā€¢11mo ago
okay folks, thanks for your time, I understand how it works now šŸ™
Pobiega
Pobiegaā€¢11mo ago
use /close