C# 9 nullable reference alert
-
when you use this new feature it create plenty of warnings... lulling us into a false sense of compiler enforced code validity.. but it's all a lie! This simple code snippet below trick the compiler and create doubly unexpected null exception :(( var list = new List(); IList ilist = list; ilist.Add(null); // no warning, all good, added! ilist.Add("hello"); //list.Add(null); // warning list.Add("hello"); Console.WriteLine(list[0].Length); // no null warning Console.WriteLine(list[1].Length); EDIT I guess perhaps I would simply have to change my expectation and get used to it.... But it started with a disappointment... This is only compiler sugar coating, no runtime change. EDIT2 I had too high and unrealistic expectation from all the buzz.... Look there is even a list of [Known Pitfalls on the concept MSDN page](https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references#known-pitfalls). I guess backward compatibility is a bitch... My top #1 annoying null from that MSDN page:
var array = new string[10];
all the strings in this array are null, obviously. But the compiler will act as if it didn't know! :laugh:
A new .NET Serializer All in one Menu-Ribbon Bar Taking over the world since 1371!
-
when you use this new feature it create plenty of warnings... lulling us into a false sense of compiler enforced code validity.. but it's all a lie! This simple code snippet below trick the compiler and create doubly unexpected null exception :(( var list = new List(); IList ilist = list; ilist.Add(null); // no warning, all good, added! ilist.Add("hello"); //list.Add(null); // warning list.Add("hello"); Console.WriteLine(list[0].Length); // no null warning Console.WriteLine(list[1].Length); EDIT I guess perhaps I would simply have to change my expectation and get used to it.... But it started with a disappointment... This is only compiler sugar coating, no runtime change. EDIT2 I had too high and unrealistic expectation from all the buzz.... Look there is even a list of [Known Pitfalls on the concept MSDN page](https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references#known-pitfalls). I guess backward compatibility is a bitch... My top #1 annoying null from that MSDN page:
var array = new string[10];
all the strings in this array are null, obviously. But the compiler will act as if it didn't know! :laugh:
A new .NET Serializer All in one Menu-Ribbon Bar Taking over the world since 1371!
Super Lloyd wrote:
all the strings in this array are null, obviously
Too bad they aren't initialized (as a string) to "0xBAADF00D"! :laugh:
The Science of King David's Court | Object Oriented Programming with C++
-
Super Lloyd wrote:
all the strings in this array are null, obviously
Too bad they aren't initialized (as a string) to "0xBAADF00D"! :laugh:
The Science of King David's Court | Object Oriented Programming with C++
Or
0xDEADBEEF
. :)
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
when you use this new feature it create plenty of warnings... lulling us into a false sense of compiler enforced code validity.. but it's all a lie! This simple code snippet below trick the compiler and create doubly unexpected null exception :(( var list = new List(); IList ilist = list; ilist.Add(null); // no warning, all good, added! ilist.Add("hello"); //list.Add(null); // warning list.Add("hello"); Console.WriteLine(list[0].Length); // no null warning Console.WriteLine(list[1].Length); EDIT I guess perhaps I would simply have to change my expectation and get used to it.... But it started with a disappointment... This is only compiler sugar coating, no runtime change. EDIT2 I had too high and unrealistic expectation from all the buzz.... Look there is even a list of [Known Pitfalls on the concept MSDN page](https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references#known-pitfalls). I guess backward compatibility is a bitch... My top #1 annoying null from that MSDN page:
var array = new string[10];
all the strings in this array are null, obviously. But the compiler will act as if it didn't know! :laugh:
A new .NET Serializer All in one Menu-Ribbon Bar Taking over the world since 1371!
All sense of compiler-enforced code validity is an illusion. Even fixing compiling errors doesn't provide validity guarantee. Warnings, long before nullable was a thing, served the same purpose. You can fix a type mismatch warning by reading the code, understanding what it's doing, how it's doing what it's doing and why it's doing it this way, or you just stick a cast in it and hope for it to pass the test suite. Which it usually does, but since the test suite doesn't catch all edge cases customers may come up with, it will blow up later. Muuuuch later. Nullable is really just the same pill in a new bottle. That pill always comes with "... but you still gotta kinda know what you're doing, not assuming the compiler to be omniscent".
-
when you use this new feature it create plenty of warnings... lulling us into a false sense of compiler enforced code validity.. but it's all a lie! This simple code snippet below trick the compiler and create doubly unexpected null exception :(( var list = new List(); IList ilist = list; ilist.Add(null); // no warning, all good, added! ilist.Add("hello"); //list.Add(null); // warning list.Add("hello"); Console.WriteLine(list[0].Length); // no null warning Console.WriteLine(list[1].Length); EDIT I guess perhaps I would simply have to change my expectation and get used to it.... But it started with a disappointment... This is only compiler sugar coating, no runtime change. EDIT2 I had too high and unrealistic expectation from all the buzz.... Look there is even a list of [Known Pitfalls on the concept MSDN page](https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references#known-pitfalls). I guess backward compatibility is a bitch... My top #1 annoying null from that MSDN page:
var array = new string[10];
all the strings in this array are null, obviously. But the compiler will act as if it didn't know! :laugh:
A new .NET Serializer All in one Menu-Ribbon Bar Taking over the world since 1371!
Not sure what you're expecting here. `IList` has no knowledge of the type of its elements. Both the parameter to [`Add`](https://docs.microsoft.com/en-us/dotnet/api/system.collections.ilist.add) and the returned element of the [indexer](https://docs.microsoft.com/en-us/dotnet/api/system.collections.ilist.item) are typed as `object?` to be as wide as possible. You'd have the same problem here: var lst = new List(); IList ilist = lst; ilist.Add("Lorem ipsum");
-
Not sure what you're expecting here. `IList` has no knowledge of the type of its elements. Both the parameter to [`Add`](https://docs.microsoft.com/en-us/dotnet/api/system.collections.ilist.add) and the returned element of the [indexer](https://docs.microsoft.com/en-us/dotnet/api/system.collections.ilist.item) are typed as `object?` to be as wide as possible. You'd have the same problem here: var lst = new List(); IList ilist = lst; ilist.Add("Lorem ipsum");
I expect what's the hype was about. I.e. for nullable reference to be the best thing since sliced bread!
A new .NET Serializer All in one Menu-Ribbon Bar Taking over the world since 1371!
-
when you use this new feature it create plenty of warnings... lulling us into a false sense of compiler enforced code validity.. but it's all a lie! This simple code snippet below trick the compiler and create doubly unexpected null exception :(( var list = new List(); IList ilist = list; ilist.Add(null); // no warning, all good, added! ilist.Add("hello"); //list.Add(null); // warning list.Add("hello"); Console.WriteLine(list[0].Length); // no null warning Console.WriteLine(list[1].Length); EDIT I guess perhaps I would simply have to change my expectation and get used to it.... But it started with a disappointment... This is only compiler sugar coating, no runtime change. EDIT2 I had too high and unrealistic expectation from all the buzz.... Look there is even a list of [Known Pitfalls on the concept MSDN page](https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references#known-pitfalls). I guess backward compatibility is a bitch... My top #1 annoying null from that MSDN page:
var array = new string[10];
all the strings in this array are null, obviously. But the compiler will act as if it didn't know! :laugh:
A new .NET Serializer All in one Menu-Ribbon Bar Taking over the world since 1371!
Nullables can be extremely useful and the dotNet framework has done a good job of implementing them consistently. The reality is that it is extremely difficult, and I suspect impossible (thank you Kurt Gödel for the proof that no formal system is complete) for a static analysis to find all errors in code. This is why we debug code at runtime. Bottom line, don't depend on any compiler to alert you to runtime bugs.
-
when you use this new feature it create plenty of warnings... lulling us into a false sense of compiler enforced code validity.. but it's all a lie! This simple code snippet below trick the compiler and create doubly unexpected null exception :(( var list = new List(); IList ilist = list; ilist.Add(null); // no warning, all good, added! ilist.Add("hello"); //list.Add(null); // warning list.Add("hello"); Console.WriteLine(list[0].Length); // no null warning Console.WriteLine(list[1].Length); EDIT I guess perhaps I would simply have to change my expectation and get used to it.... But it started with a disappointment... This is only compiler sugar coating, no runtime change. EDIT2 I had too high and unrealistic expectation from all the buzz.... Look there is even a list of [Known Pitfalls on the concept MSDN page](https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references#known-pitfalls). I guess backward compatibility is a bitch... My top #1 annoying null from that MSDN page:
var array = new string[10];
all the strings in this array are null, obviously. But the compiler will act as if it didn't know! :laugh:
A new .NET Serializer All in one Menu-Ribbon Bar Taking over the world since 1371!
I would expect code that casts a
List<string>
to aIList
to manage nulls. If I just want to return a simpler interface, I'd cast toIList<string>
. -
when you use this new feature it create plenty of warnings... lulling us into a false sense of compiler enforced code validity.. but it's all a lie! This simple code snippet below trick the compiler and create doubly unexpected null exception :(( var list = new List(); IList ilist = list; ilist.Add(null); // no warning, all good, added! ilist.Add("hello"); //list.Add(null); // warning list.Add("hello"); Console.WriteLine(list[0].Length); // no null warning Console.WriteLine(list[1].Length); EDIT I guess perhaps I would simply have to change my expectation and get used to it.... But it started with a disappointment... This is only compiler sugar coating, no runtime change. EDIT2 I had too high and unrealistic expectation from all the buzz.... Look there is even a list of [Known Pitfalls on the concept MSDN page](https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references#known-pitfalls). I guess backward compatibility is a bitch... My top #1 annoying null from that MSDN page:
var array = new string[10];
all the strings in this array are null, obviously. But the compiler will act as if it didn't know! :laugh:
A new .NET Serializer All in one Menu-Ribbon Bar Taking over the world since 1371!
Wow, really interesting example. My personal experience has been really positive with Null Reference Types, and it's caught many real world issues long before production, but good to have a cold reminder. I guess I normally consider the point of NRT for me is that it increases the chance that the compiler at least puts the developer to the decision, so if it's a mistake it's a conscious one. This is a good example where that can't be guaranteed. Let me try a counter argument to the
IList
example, if not only for my own sanity and shrinking NRT world view... So, the null was permitted, not because it was added to a collection of non-nullable strings, but effectively it was added to a list of explicitly nullable objects. Yes, explicitly is not so explicit yet, but hear me out. If you now try and pluck that null object out, and use it where a null is not permitted, I believe the compiler will realise, as yourIList
is actuallyIList
, so the explicit typing is actually there, and so the compiler will save you at the last minute before the null actually becomes a problem. Based on this I think the behaviour we see is ok and probably by design.// Warning is generated when you attempt to use it, because underlying type of `object?` is recognised
string s = ilist[0];As for the array, though...? B*gger, that's scary. Maybe a bug? Weirdly it recognises
array
as beingstring[]?
after the line it's declared on, but then still does not generate a warning when reading thatstring?
back into a newstring
. EDIT: Just realised yourConsole.Writeline
bits do demonstrate you reading it out. Are there any examples that don't involve array[]
syntax? Maybe it's a bug worth raising? -
Wow, really interesting example. My personal experience has been really positive with Null Reference Types, and it's caught many real world issues long before production, but good to have a cold reminder. I guess I normally consider the point of NRT for me is that it increases the chance that the compiler at least puts the developer to the decision, so if it's a mistake it's a conscious one. This is a good example where that can't be guaranteed. Let me try a counter argument to the
IList
example, if not only for my own sanity and shrinking NRT world view... So, the null was permitted, not because it was added to a collection of non-nullable strings, but effectively it was added to a list of explicitly nullable objects. Yes, explicitly is not so explicit yet, but hear me out. If you now try and pluck that null object out, and use it where a null is not permitted, I believe the compiler will realise, as yourIList
is actuallyIList
, so the explicit typing is actually there, and so the compiler will save you at the last minute before the null actually becomes a problem. Based on this I think the behaviour we see is ok and probably by design.// Warning is generated when you attempt to use it, because underlying type of `object?` is recognised
string s = ilist[0];As for the array, though...? B*gger, that's scary. Maybe a bug? Weirdly it recognises
array
as beingstring[]?
after the line it's declared on, but then still does not generate a warning when reading thatstring?
back into a newstring
. EDIT: Just realised yourConsole.Writeline
bits do demonstrate you reading it out. Are there any examples that don't involve array[]
syntax? Maybe it's a bug worth raising?In the known caveat of the nullable reference, they mention that structs can be another source of unexpected null. [Nullable reference types | Microsoft Docs](https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references#known-pitfalls)
A new .NET Serializer All in one Menu-Ribbon Bar Taking over the world since 1371!