Asked by:
Essential .NET - C# 8.0 and Nullable Reference Types

General discussion
-
Despite his love for C#, Mark Michaelis acknowledges it isn’t a perfect language. In particular, its handling of null references types has been problematic since the language’s inception. That issue should be considerably improved in C# 8.0.
Read this article in the February 2018 issue of MSDN Magazine
Thursday, February 1, 2018 7:04 PM
All replies
-
I have no problem with reference types always being nullable. What I have a problem with is this whole "?" nullable syntax. I hate it. THAT, to me, is the pollution of the language. And what you have described is only going to make it worse and more confusing.Friday, February 2, 2018 2:20 PM
-
"There’s no way to decorate parameters to not allow null." It's true, but JetBrains provide a bunch of custom attributes in Jetbrains.Annotations namespace, for example NotNullAttribute and CanBeNullAttribute that can be used for that purpose. They will show warnings in IDE given JetBrains ReSharper is active and an incorrect value is passed to the method parameter marked with the attribute. The value has to be detected statically, of course.
No ads, it's just I'm working with the code that has those attributes put here and there, so I decided to make use of them.
- Edited by VladimirTi Saturday, February 3, 2018 4:43 PM
Saturday, February 3, 2018 4:42 PM -
After all my years of programming and software engineering, this seems rather excessive. Response:
- string? text = null; string is a reference and by default set to null. Primitive types like int, char, byte, and double are not null by default and can use the nullable operator. Expecting references to be null is a given and already provided for. This idea is overcomplicating the issue and not a convenience.
- string! text = "Inigo Montoya" or myReference! = new myReference() can be useful. If something does make it null, something will flash you a warning.
- string text = GetText(); If you don’t know what this case is, you are missing the point of using references.
- In the example: Console.WriteLine( text2.Length ); if you are not checking your code (text2) for null, then you better go back to programmer school.
Some things that would be helpful in C# (derived from C++) using const:
- Const member methods. For example:
class Date
{
int getMonth() const
{
return month; // Doesn't modify anything
}
}
The method getMonth() does not modify the Date class. If the programmer should try to modify data in the class from within the getMonth() method, the compiler would flag an error. This protects the programmer from making an unintended data modification.
- Const method parameters.
class MyClass
{
bool isYoung(const Person person)
{
return (person.Age < 20); // Doesn't modify anything in person
}
}
This is useful to protect the input parameter referenced so that no data gets changed. If the programmer tries to modify the input object, then the compiler will flag an error.
- Edited by James Lonero Monday, February 5, 2018 7:48 PM
Monday, February 5, 2018 7:45 PM -
With reference to content related to LINQ, I have one question: Is there any plan to make better syntax for left/right/full outer joins? Currently the syntax is very cumbersome.
Wednesday, February 7, 2018 6:10 AM -
Indeed, this would mean that we'd have to add ? to every single automatic property.
public class Person { public string Name { get; set; } } var person = new Person(); //person.Name, which is not-nullable could be null here. Console.WriteLine(person.Name.Length);
See how this would actually break C#?
Wednesday, February 7, 2018 9:34 PM -
The syntax change just mean that Entity Framework like automatic templates can enforce "not null" in string types fields in simpler way.
And it enables "easier to write" template generation, whenever you see it's field that can be null, you add "?" after the type declaration; if it can't, just don't add the "?".
Of course, for we human who is more used to traditional C semantics on the rules on value type and reference type, this feels weird to read.
And it introduce trouble to forums too - when someone post code to troubleshoot problem, we have to ask whether it's C# 8+ or we'd miss important checks.
And for those who "copy and paste" code from the web, if their company uses C#8.0+, the code logic will like need to be inverted.
So let's see how well will it goes... although I have feeling that it will not go well.
Thursday, February 8, 2018 1:38 AM -
So if this returns null...
var s1 = default(string);
what will this return...or will this not be allowed?
var s2 = default(string?);
Thursday, February 8, 2018 8:01 AM -
When "default(int?)" returns null, naturally so does "default(string?)".
- Edited by cheong00 Thursday, February 8, 2018 8:15 AM
Thursday, February 8, 2018 8:15 AM -
Oh my...
- Replace NullableAttribute with NotNullAttribute
- Throw away all other bulls*t
- It's done!
Thursday, February 8, 2018 9:09 AM - Replace NullableAttribute with NotNullAttribute
-
I don't get the point of this. Is it supposed to solve an actual problem or is it just for the benefit of people who don't understand the difference between a value type and a reference type? You know, the kind of people who don't really understand what's going on and will just stick a NullAttribute operator on the end of the type declaration when the compiler complains just to make the warning go away and still end up with a NullReferenceException in their code.Thursday, February 8, 2018 5:22 PM
-
This looks like a bunch of solutions in search of the problems.
You do realize that if you put nullable syntax as optional compiler switch that nobody will use it? Please, please, please don't make breaking changes in C#, we have sucha large code base that this will effectively preclude us from advancing to new C#. And I am sure we are not the only ones.
If you must put the non-nullable syntax in place (string!) for reference types and be done. There is a reason why reference and value types are NOT the same and should not be treated the same.
- Edited by mmix2000 Friday, February 9, 2018 10:33 AM
Friday, February 9, 2018 10:32 AM -
i agree with the guy who said "This looks like a bunch of solutions in search of the problems"
this is the first time I was totally perplexed reading about a new feature in c# lang. This is unnecessary, it seems to me there is some internal policy/memo in the compiler team "no matter what happens, we need a new language feature after every X amount of time". Guys, you are not maintaining a bogus Youtube channel where you MUST put a new video every 2 days, this is a very complex domain of computer programming, keep it simple, take half a decade for feature designing if you must, and when it finally makes sense to not only you but the community as well, only then make the changes to language.
When I get null reference exception, yes its a bug, and its MY bug, there is nothing you can do to stop that, I will have to train myself to be better at writing code. Also, I need my variable to be null as long as I want to, do not try to spoon feed me telling me "hey you dummy programmer, i will tell you a way to avoid a null reference in all use cases no matter what"! No dont do that. Again I am totally fine with my null reference exceptions, a null references exception means i _forgot_ to write some logic that was meant to be there, it doesnt make any sense to tell me there is going to be a default logic inplace to save you from the null reference when the default logic was as bogus as the null reference itself! I dont want the default logic (hiding null reference) covering up my mistakes, nothing is good enough in that case, because its the programmer that messed up, and he/she needs to now solve it.
Guys my command on english language is not ideal, but I hope i have expressed my point clear enough, hoping this feature doesnt make it to the final product.
PS: compiler features are not like UI buttons so you could say "hey if you dont like it dont click it". Hope you get the point.Ab
Sunday, February 11, 2018 6:43 PM -
i agree with the guy who said "This looks like a bunch of solutions in search of the problems"
...
When I get null reference exception, yes its a bug, and its MY bug, there is nothing you can do to stop that, I will have to train myself to be better at writing code. Also, I need my variable to be null as long as I want to, do not try to spoon feed me telling me "hey you dummy programmer, i will tell you a way to avoid a null reference in all use cases no matter what"! No dont do that. Again I am totally fine with my null reference exceptions, a null references exception means i _forgot_ to write some logic that was meant to be there, it doesnt make any sense to tell me there is going to be a default logic inplace to save you from the null reference when the default logic was as bogus as the null reference itself! I dont want the default logic (hiding null reference) covering up my mistakes, nothing is good enough in that case, because its the programmer that messed up, and he/she needs to now solve it.
I wish I could upvote this twice.
This is a bandaid on a non-issue that will only encourage bad practices and programmer laziness. I honestly think this will push the problem into far more subtle bugs that are much harder to diagnose and eliminate because they'll be based around assumptions and ignorance of the compiler and how object references should actually work.
Need an example of this? Get 1,000 .NET programmers of varying levels of experience into a room. Ask them if they believe System.String is a structure or a class. You WILL get a mish-mash of results, particularly from the less experienced ones. This is in no small part due to the language and compiler hiding some of the object initialization code for strings in order to make them behave like an intrinsic structure. It's better than having to call a constructor to assign a value to a new string and it makes the code more concise, but it makes the true nature of System.String far less intuitive/obvious to newbies.
That's for one type. One. Imagine if we start hacking up the language to make classes behave like structures and structures behave like classes everywhere. Of all the areas to improve the language, this didn't seem to be particularly high up the list, and the responses on this thread seem to be echoing that sentiment.
Monday, February 12, 2018 8:11 PM -
Any idea as to when C# 8 will be available?
Mike
Wednesday, February 14, 2018 12:04 AM -
I suspect the C# team are bored and need to invent a problem to keep themselves in a Job. This is ludicrous. Don't break the language.Thursday, February 22, 2018 1:21 AM
-
This is far from a non-issue, and the null pointer/reference dereferencing issue is a solved problem in other languages that explicitly denote nullability in the type system.
For anyone complaining that this will clutter up your code base, the fact of the matter is that the vast majority of references in a code base are non-nullable. This means that the sane and default choice when declaring a reference is that it be non-nullable. Try using a language like Kotlin to see how much safer code becomes (as it relates to this issue), and how much more clear and obvious. Throwing null checks everywhere at function entry points for arguments or checking return values is (1) cluttering, (2) error prone, and (3) inefficient from a program perspective. Having nullability be explicitly represented immediately rules out these issues.
The inventor of null argued that it was his billion dollar mistake. Look it up.
I greatly welcome this change to C#. It's about time we get rid of unsafe language constructs.- Edited by azth Wednesday, February 28, 2018 4:54 AM
Wednesday, February 28, 2018 4:53 AM -
>For anyone complaining that this will clutter up your code base, the fact of the matter is that the vast majority of references in a code base are non-nullable. This means that the sane and default choice when declaring a reference is that it be non-nullable.
Now you've got to choose what is the default value for class reference members. Even if you exempt the rule for autogenerated getter/setters properties, there are still people who use internal variable to store actual value because they need some processing when the value changes.
And even if we restrict the scope of discussion to string types, on a production system with nullable string fields, unless the POCO framework providers update their code to generate new types with string? for nullable string field, the developers will bang their head hard when use it, declare it as show stopper, and revert it to current way, or if there's no switch to alter this behavior, revert to whatever previous version of .NET framework that is unaffected by this behavior.
I'd welcome this change if it comes from day 1 when C# is introduced, but introducing this at this late stage will be a very costy change - for companies which use it, and for community which supports it.
Thursday, March 1, 2018 1:46 AM -
Next thing you know int will default to 1 rather than 0 in order to avoid DevideByZeroException. Come on.
P.S. Having null exceptions IMO is better than letting wrongly uninitialized non-nullable reference types wander in the code. But hey what do I know?
- Edited by yazanpro Tuesday, May 8, 2018 4:45 AM
Tuesday, May 8, 2018 4:44 AM -
As someone who's been spending a good deal of time with Kotlin, I'm very happy to see this change for C#. Cute that people are trying to bravado like "this only matters if you're bad and don't understand how references work", but can they really say they haven't encountered a NullReferenceException in the last six months of coding? Because that's something I can say with using Kotlin. The added layer of type-safety just makes your life a lot easier especially when dealing with other people's libraries. Do we assume a return will never be null? Do we add null checks for every single variable? And you pretty much have to if you're writing a library and excepting other people's variables. Well, now we can just specify not-null and not worry about it. And think about it from a declarative perspective. You ask for a Chair and somebody gives you a Chair box with nothing in it. Would be nice to have it tell them at compile time (and even before) that "there needs to be a Chair in here" rather than throwing a runtime error or bending over backwards to try and figure out an elegant way to handle the situation.
Now all you need is a less-verbose way to mark immutable variables to signify their place as a fundamental variable archetype (and really the thing that you should be using 99% of the time) rather than some special case. "readonly var" is clear enough, sure, but it's a bit of a mouthful.Thursday, May 10, 2018 2:34 PM -
I really like the fact that you can make value types nullable to indicate that they are not initialized and probably do not use memory yet. Especially with large struct variables this is helpful as long as they are not used in the program.
I like it that you can immediately recognise from the ? whether it's a value type and whether this value type is nullable (especially with struct/enum where you cannot see it by the name).
I like it that all class types and arrays are references (without ?) and these are null without assignment or can be set to null later. This ensures that they don't need memory when declared and don't execute superfluous initialization code. This should always be the default.
The article does not discuss what content an object would contain (e.g. 'MyClassWithThousandsOfVariablesOrOpenedResources! myObject;') if it were made non-nullable with !. The article leaves open questions. Does the object occupy memory from the beginning? Shouldn't there be a new kind of constructor here? Probably not.
The use of ! to declare reference types as non-nullable could be introduced as a language extension. It can be useful in many cases (e.g. for strings and arrays). But, if you would allow this, similar to C++:
class MyClass
{
MyClass() {}
MyClass(int x) {}
}MyClass myObject1(); // is an instance
MyClass myObject2(5); // is an instance
MyClass myObject3; // is null... then you wouldn't need a ! for not-nullable references. In C#, myObject1 and myObject2 would still remain a reference, where you wouldn't have the possibility anywhere to set it to null. The compiler should not allow this. But that also means that you cannot assign another instance to myObject1 or myObject2.
I don't like the use of ? to declare reference types as nullable. 'MyClass myObject;' should always be null, without having to specify a ?. This should be seen separately from the ability to make reference types non-nullable with !.
If you would allow 'MyClass?' and 'MyClass!', you would also have to ask if you would have to introduce 'MyStruct!' to say a struct variable has a value. You don't have to ask this if you doesn't introduce 'MyClass?'.
I don't like it to maintain a compiler switch in all C# development environments in the future. This would not only have to be available for an IDE with C# 8.0, but also for C# 18.0 in 10 years. So far no compiler switch is necessary at all.
Whatever you introduce as a language extension, it should not be in the form of attributes. (For example, I would have preferred if they had introduced a new keyword instead of FlagsAttribute.)
As far as my thoughts on it.
- Edited by Heiko65456465 Thursday, September 6, 2018 2:31 PM
Wednesday, September 5, 2018 4:22 PM -
This is great news! To anyone who expresses frustration at the idea of enabling an option to code more strictly: it's a goddamn option you knobs, if you don't like it, don't enable it in your project.
The problem remains that `null` is a true cancer for code, especially in langages like C# and JS. I am GLAD that teams in Microsoft are working toward eradicating it. They already had made strides with TypeScript and its strict mode, this is the next great step.
This is a bandaid on a non-issue that will only encourage bad practices and programmer laziness
The laziness was to assign `null` in the first place, i don't know how having to mark a reference as “potentially null” is lazier.
When I get null reference exception, yes its a bug, and its MY bug
This is not a “good devs vs. newbies” fight, nor a “corporate begging for useless features vs. poor devs” one. If you're still thinking that features in a langage are only added to cater to “people who don't know how the langage works”, maybe you should get off your ivory tower and accept that life can be simpler for you too, even if you have “all those years of experience”.
compiler features are not like UI buttons so you could say "hey if you dont like it dont click it". Hope you get the point.
Compilers work like this, though. Just for C#, there are about multiple features that need to be enabled with a #define (like code contracts), and others compiled langages do this as well. This tells a lot about what some people know of compilers and langage features.
There is so much more to C# than a simple switch to enable a null-strict mode, i pity anyone who feels that complaining about their life being made safer is of major importance.
- Edited by Octopus in a tee-shirt Sunday, February 3, 2019 9:17 AM
Sunday, February 3, 2019 9:15 AM -
Well we do have the
in
modifier from C# 7.2, which offers what you want from a const method parameter.
Tuesday, February 19, 2019 2:21 PM