Warm reminder : The new C # 8 feature mentioned in this article has been proposed, but it does not mean that C # 8 will be released when it is officially published. This means that my notes may have been written in vain, and that you don't have to be in a hurry to understand all the details of this new feature, and perhaps just glance at the "summary" below to say it is enough.
Profile
C # 8 's Nullable Reference Types means that all of the reference assumptions are not NULL, and for nullable reference types, the notation is the same as the nullable physical type, and the declaration must be preceded by a "?" character in the type's face. Please look at the following example:
1 int? num =NULL;//can be null (physical type)2 string? UserName =NULL;//can be null (reference type)3 stringPassword =NULL;//Edit Warning: not null!4Employee? EMP =NULL;//can be null (reference type)5User User =NULL;//Edit Warning: not null!
This new feature has a lot of detail, and it's not easy to get a few words. Therefore, the next is more redundant, and more detailed to explain.
Bulk Synopsis:
- Foundational knowledge
- What is Nullable Reference Types?
- Why do I need Nullable Reference Types?
- Forbid the Null reference type
-Default expression
- Allowable Null Reference type
-Meditation Path Analysis
- Installation Tools
-Sharplab.io
-Installation expansion function: Nullable Reference Types Preview
- Edit both items
-Adjustment of the translator's warning
Foundational knowledge
All along, C # developers are already familiar with the meanings represented by the physical type (value types) and the reference type (reference types), and the difference between them:
- When declaring a physical variable (for example, int i), the translator will set it to the preset value if it is not given the initial value. For example, the preset value for the int type is 0.
- If you want to make the variable value of the actual type NULL, use the generic structure system.nullable<t> , where T must be the actual type. This generic structure can be used in C # in a more simplified T? language, such as int? equivalent to Nullable<int>, which represents a nullable integer.
- When declaring a variation of a reference type (for example, string s), if the initial value is not given, then its preset value is null. That is to say, the variables of the reference type can be null.
So, since the reference type can be a null,c# 8 (project) What's new in the feature is called "can be an empty reference type" (Nullable Reference Types)? What is it exactly?
Note: If you want to read the code and knock it into the experiment, you can jump to the back and find out about the installation of the C # 8 experimental extensibility feature.
What is Nullable Reference Types?
In simple words, before C # 8, the reference type is NULL, and this is where C # 8 will start to change: All reference types are not NULL, and if you want to make a variable of a reference type NULL, you must declare that it is "nullable". Please look at the following example:
string null; // C # 7.x ok,c# 8 Etymology warning. stringnull// C # 7.x edit failed, C # 8 O
The 1th line of code will appear in C # 8 with the following edit warning:
Warning cs8600:cannot convert NULL to non-nullable reference.
Because string is a reference type, and as just mentioned, the participation type is not the same as C # 8 has been changed to a preset is not NULL, so the editor will be issued a warning that you can not assign NULL to the "non-null reference".
On the other hand, the 2nd line of code is not a problem in C # 8, and if you use C # 7.2 or earlier, the editor will be wrong:
Error cs0453:the type ' String ' must is a non-nullable value type in order to use it as parameter ' T ' in the generic type or method ' nullable<t> '
Is this because of string? is the C # 8 Nullable Reference Types language, which indicates that a nullable string change is to be declared. C # 7.2 There is no such language, and it will be wrong to edit the translation.
As you can see, the "Nullable reference type" and the "nullable physical type" approach to C # 8 have been unified: when declaring, add a question to the type ('? '). )。
Why do I need Nullable Reference Types?
Prior to C # 8, there were two possible variables for the reference type: null or NOT NULL, the translator was not able to help, so we often added some "shields" when dealing with the variables, that is, whether the variables were null, for example:
1 Static int Length (string text)2{3 returnnull 0 : Text. Length; 4 }
In the example above, when we write the Length function, there is no way to make sure that the incoming argument text has no value. If you do not first check whether the variable is null and trade its own nature or method, then when the program is executed, as long as the caller is passing in a null, the NullReferenceException type of mistake will occur. However, it is difficult to write a program in some places will forget to add a null check, anti-protection, this part can be a translator to help a bit busy? (C # 8 means: Very happy!)
As can be seen from the above example, the existing reference type is not sufficient for the null language. We need more accurate language to express the following images:
- A reference type variable can be null, so when you access the object represented by the variable, you must first check if it is null.
- The variation of a reference type must point to an object, not to null.
Before C # 8, we already had the first. C # 8 is to meet the second requirement, so join Nullable Reference Types. Moreover, it wants the developers to be able to specify that the variable of a reference type is NULL when the program is written, and that if the designation is not understood, the preset is not NULL. In this way, the translator can assist in checking null for this kind of tedious work, so that when we write the program, we can avoid the problems that might occur when the program is executed.
The purpose of this feature in C # 8 is to help reduce the chance of a nullreferencexception, rather than a guaranteed total, where there are too many "eyebrows" and loopholes that are not easy to achieve.
Forbid the Null reference type
In a just example, if you want the text argument of the Length method to forbid null, the original code does not have to be changed at all, still the original:
1 Static int Length (string text)2{3 returnnull0 : Text. Length; 4 }
The C # 8 editor will think that the parameters text must have a value. Therefore, when the caller is sending null, for example:
int i = Length (null);
At this time, the translator can check that the call is buried with the NullReferenceException's risk, thus showing the edit warning message. It's important to note that it's just a warning, not a typo--that's not going to happen because the development tool (the editor) has been promoted and the existing items suddenly appear in a lot of wrong translations.
Also because it's just a warning, so there's already a null-check hood, so it's best to take it off. Like the following, there is a suspicion of self-martial:
1 Static int Length (string text)2{3 return// pre-check Null protection take off (bad!). 4 }
Because, if the developers ignore the warning from the C # 8 Editor: "This assigns null to a variable that is not NULL." "Then the program will be able to show the notorious mistake."
Default expression
When you give a preset value to a non-nullable reference type, the C # 8 editor warns you:
string default; // Edit warning: assigning null to non-null variables
Allowable Null Reference type
Continuation of the previous example, if you want the text to accept NULL, you need to use the new language of C # 8, that is, when declaring the variable, the back of the type plus a question. As shown below:
1 Static int Length (string// text can be entered null.) 2{3 returnnull0 : text. Length; 4 }
The C # 8 editor will encode the above code into a similar way:
1 Public Static int string s) 2 {3 return NULL 0 : s.length; 4 }
The full name of the [Nullable] feature is System.Runtime.CompilerServices.NullableAttribute .
Meditation Path Analysis
The translator parses the path of the code in order to catch a place where the NullReferenceException may occur. Please look at the following example:
1 Static intLength (string? S//The parameters s can be null. 2 {3 if(s = =NULL)//Check if S is null first4 return 0;//is null to return 0. 5s =NULL;//s becomes null again!6 returnS.length;//The translator is still able to detect, and warns: maybe null!7}
However, the code static analysis can not do 100%. It should be said that the static analysis can only be used to check the method itself for the declaration of the parameters and the region variables involved in the program logically, but could not go deep into the method called other methods. In just a few examples:
1 Static int Length (string? s)2{3 if// Edit warning: CS8604. 4 return0; 5 return // Edit Warning: CS8602. 6 }
This is a safe way to write, and the editor actually shows two warnings! The distinction is:
- Warning cs8604:possible null reference argument for parameter ' value ' in ' bool string. IsNullOrEmpty (string value) '.
- Warning cs8602:possible dereference of a null reference.
The reason for warning CS8604 is that we are sending a nullable string variable s to a non-null reference (the isnullorempty is declared as a string s , so it is not be null).
The reason for the warning CS8602 is that, as mentioned earlier, the code static analysis will not go deep into the next layer of call, so it is not possible to know whether the String.IsNullOrEmpty () is true or false. In this question, C # proposes a language that allows the developers to help the translator reduce the number of redundant warnings that are generated by the lack of in-depth code analysis. This language uses the astonishing sighs (!), like this:
1 static int Length (string ? s) 2 { 3 if (String.IsNullOrEmpty (s)) // Span style= "COLOR: #008000" > edit warning: CS8604. 4 return 0 ; 5 return s!. Length; // this line no longer causes the edit warning. 6 }
One of the s! is to tell the editor: "Hey! Here I know better than you, s certainly will not be null, and you will not charge me with caution. 」
So, another warning CS8604 how to resolve it? Now I only know these two methods:
- Suppress this warning by editing the option or the pre-processor instructions #pragma.
- Use if (s = = null) instead.
and the official GitHub document: The C # Nullable Reference Types Preview mentions string. IsNullOrEmpty 's question, the above answer is:
We is investigating allowing annotations on methods this describe simple relationships between parameters and Retur n value with respect to null values. The compiler could use those annotations when analyzing the calling code.
Just wait and see and continue to show.
The part of the language is first written here. Next is the more relaxed part: the installation and setting of the tool.
Installation Tools
Want to try C # 8 new Nullable Reference Types, I've tried two methods, one is the Roslyn expansion function with Visual Studio 2017 plus the version Nullable Reference Types P Review; Another way is to use the browser to open the Https://sharplab.io, directly on the line to edit and Test C # 8 new features.
If you don't want to "dirty" your current development environment, then Sharplab.io will be a bad choice. Of course, it's a bit slower to respond than Visual Studio 2017.
Here are some of the ways to install or set the two tools.
Sharplab.io
Using the browser to open the Https://sharplab.io, the left side pane can enter the code, the right side pane can display the program's results or the code after the translation, including C #, VB, IL, and the JIT combination of languages (cool!). )。
If you are experimenting with C # 8 's Nullable Reference Types, you must select the corresponding version of the editor in the drop-down selection above the left pane, as shown in the following image:
Then you can tap the code to observe the program's results, the warning or wrong message displayed by the translator, and the code after the anti-translation.
Installation expansion function: Nullable Reference Types Preview
Premise: Your Visual Studio 2017 version must be 15.5.x in order to install the extensibility of this experiment.
Step:
- Close Visual Studio 2017.
- Download the Roslyn_nullable_references_preview.zip.
- Unpack the compression file you just downloaded, and then execute the Install.bat.
The next time you open the Visual Studio 2017,c# Editor, you should recognize Nullable Reference Types language.
Watch out! after installing this Roslyn, if you want to install additional updates for Visual Studio 2017, you must first remove the extensibility feature of this experiment.
It is worth mentioning that if you have modified the C # version of the project, it is a good idea to check it out: Open the object's Properties window, then select Build on the left-hand side panel, and then find the Advanced button at the bottom of the "Build Settings" window. After this button, look at Language version, as follows:
After installing the above expansion function, in my environment, the version of C # language is selected latest major version (default) or latest minor version (latest) can be used Nullable Reference Types Language, but not the other way.
These two options allow the C # design team to control what new features are coming out of our user's development environment. If you want to taste, you can choose latest minor; If you prefer a stable route, you can choose latest major (suitable for new items) after the new features have been formally developed for the purpose. To build items with older versions, choose other specific C # versions, such as C # 5, 6, or 7.2, etc. (for legacy items).
Try to edit an existing project
After installing the tools as described in the previous steps, use Visual Studio 2017 to open the C # project I wrote earlier to make a dot book, Rebuild the entire solution, and build successfully, but there are 765 warnings, as follows:
These warnings are:
- Warning cs8600:cannot convert NULL to non-nullable reference.
- Warning cs8601:possible null reference assignment.
- Warning cs8602:possible dereference of a null reference.
- Warning cs8618:non-nullable field ' Field-name ' is uninitialized.
The number of the last CS8618 is the most.
It can also be seen from here that this new feature of C # 8 does not have an "intrusive" effect on the existing C # code-I mean, it doesn't force you to rewrite or re-write the existing code. However, every time that you build a project, there are so many editing warnings that it can cause trouble. For example, some of the editing warnings that we especially care about may be difficult to find because they are in a lot of warning messages.
Warning for adjusting the translator
When using the new development tool (translator) to edit the inheritance items, to avoid producing a lot of editing warnings, the easiest way is to set the language version of the item to the older version, for example, C # 6, 7.0, 7.2, and so on. Of course, this is just as well as completely abandoning the new features of C # 8.
If you want to use some C # 8 's new language, but also to close some eye warnings, you can set the suppress warnings in the C # object window, as follows:
Or you can think of some warnings as bugs, the Treat warning as errors option in the map.
In addition, for a small number of situations, we can also add a pre-processor instruction in the program #pragma to close and restore specific warnings, like this:
#pragma // non-nullable field is uninitialized. code #pragma warning restore CS8618
Heavy Finishing
- Prior to C # 8, the reference type was nullable, and this was where C # 8 would start to change: All reference types are not NULL.
- For nullable reference types, the notation is the same as the nullable physical type, and the declaration must be preceded by a "?", such as a string? text;. This is the new C # 8 Nullable Reference Types language method.
- The intention of Nullable Reference Types is to help reduce the chance of developing NullReferenceException , rather than the assurance that it is completely du.
- Code static analysis can only check the method itself for the declaration of the parameters and the region of the variables involved in the program logically, but no way to drill down into the method of other methods called.
- For existing C # items, we can continue to use the new version of the translator without modifying the code, and through the authoring option to avoid producing a bunch of warning messages.
After writing this note, there is a sense that C # 8 intends to introduce Nullable Reference Types to reduce the problem of NullReferenceException, but it also brings some problems.
So, the day that C # 8 is officially released, will it really contain Nullable Reference Types features?
References
- The C # Nullable Reference Types Preview
- Essential. net-c# 8.0 and Nullable Reference Types
- Introducing Nullable Reference Types in C #
A preliminary study of C # 8 Nullable Reference Types