Skip to content

Commit 8536137

Browse files
authored
Create nullable migration tutorial (#10383)
* update existing nullable content for Preview 2 * draft of migration tutorial done. * proofread and edit * feedback from Scott. * non-ascii apostrophe. * codefence filename * clarify Core * respond to initial feedback * respond to final round of feedback
1 parent 5cc4fbe commit 8536137

File tree

4 files changed

+233
-41
lines changed

4 files changed

+233
-41
lines changed

docs/csharp/nullable-references.md

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: Nullable reference types
33
description: This article provides an overview of nullable reference types, added in C# 8. You'll learn how the feature provides safety against null reference exceptions, for new and existing projects.
4-
ms.date: 12/03/2018
4+
ms.date: 02/19/2019
55
---
66
# Nullable reference types
77

@@ -19,6 +19,8 @@ This new feature provides significant benefits over the handling of reference va
1919
- **A reference can be null**. No warnings are issued when a reference type is initialized to null, or later assigned to null.
2020
- **A reference is assumed to be not null**. The compiler doesn't issue any warnings when reference types are dereferenced. (With nullable references, the compiler issues warnings whenever you dereference a variable that may be null).
2121

22+
With the addition of nullable reference types, you can declare your intent more clearly. The `null` value is the correct way to represent that a variable doesn't refer to a value. Don't use this feature to remove all `null` values from your code. Rather, you should declare your intent to the compiler and other developers that read your code. By declaring your intent, the compiler informs you when you write code that is inconsistent with that intent.
23+
2224
A **nullable reference type** is noted using the same syntax as [nullable value types](programming-guide/nullable-types/index.md): a `?` is appended to the type of the variable. For example, the following variable declaration represents a nullable string variable, `name`:
2325

2426
```csharp
@@ -35,18 +37,57 @@ name!.Length;
3537

3638
You can read details about this operator in the [draft nullable reference types](https://github.com/dotnet/csharplang/blob/master/proposals/nullable-reference-types-specification.md#the-null-forgiving-operator) specification proposal on GitHub.
3739

40+
## Nullability of types
41+
42+
Any reference type can have one of four *nullabilities*, which describes when warnings are generated:
43+
44+
- *Nonnullable*: Null can't be assigned to variables of this type. Variables of this type don't need to be null-checked before dereferencing.
45+
- *Nullable*: Null can be assigned to variables of this type. Dereferencing variables of this type without first checking for `null` causes a warning.
46+
- *Oblivious*: This is the pre-C# 8 state. Variables of this type can be dereferenced or assigned without warnings.
47+
- *Unknown*: This is generally for type parameters where constraints don't tell the compiler that the type must be *nullable* or *nonnullable*.
48+
49+
The nullability of a type in a variable declaration is controlled by the *nullable context* in which the variable is declared.
50+
3851
## Nullable contexts
3952

40-
Nullable contexts enable fine-grained control for how the compiler interprets reference type variables. The nullable context of any given source line is `enabled` or `disabled`. You can think of the pre-C# 8 compiler as compiling all your code in a `disabled` nullable context: Any reference type may be null. Warnings are not generated when variables of a reference type are dereferenced.
53+
Nullable contexts enable fine-grained control for how the compiler interprets reference type variables. The **nullable annotation context** of any given source line is `enabled` or `disabled`. You can think of the pre-C# 8 compiler as compiling all your code in a `disabled` nullable context: Any reference type may be null. The **nullable warnings context** may be set to `enabled`, `disabled`, or `safeonly`. The nullable warnings context specifies the warnings generated by the compiler using its flow analysis.
54+
55+
The nullable annotation context and nullable warning context can be set for a project using the `NullableContextOptions` element in your `csproj` file. This element configures how the compiler interprets the nullability of types and what warnings are generated. Valid settings are:
4156

42-
The nullable context is controlled using a new pragma:
57+
- `enable`: The nullable annotation context is **enabled**. The nullable warning context is **enabled**.
58+
- Variables of a reference type, `string` for example, are non-nullable. All nullability warnings are enabled.
59+
- `disable`: The nullable annotation context is **disabled**. The nullable warning context is **disabled**.
60+
- Variables of a reference type are oblivious, just like earlier versions of C#. All nullability warnings are disabled.
61+
- `safeonly`: The nullable annotation context is **enabled**. The nullable warning context is **safeonly**.
62+
- Variables of a reference type are nonnullable. All safety nullability warnings are enabled.
63+
- `warnings`: The nullable annotation context is **disabled**. The nullable warning context is **enabled**.
64+
- Variables of a reference type are oblivious. All nullability warnings are enabled.
65+
- `safeonlywarnings`: The nullable annotation context is **disabled**. The nullable warning context is **safeonly**.
66+
- Variables of a reference type are oblivious. All safety nullability warnings are enabled.
4367

44-
- `#nullable enable` sets the nullable context to enabled.
45-
- `#nullable disable` sets the nullable context to disabled.
68+
You can also use directives to set these same contexts anywhere in your project:
69+
70+
- `#nullable enable`: Sets the nullable annotation context and nullable warning context to **enabled**.
71+
- `#nullable disable`: Sets the nullable annotation context and nullable warning context to **disabled**.
72+
- `#nullable safeonly`: Set the nullable annotation context to **enabled**, and the warning context to **safeonly**.
73+
- `#nullable restore`: Restores the nullable annotation context and nullable warning context to the project settings.
74+
- `#pragma warning disable nullable`: Set the nullable warning context to **disabled**.
75+
- `#pragma warning enable nullable`: Set the nullable warning context to **enabled**.
76+
- `#pragma warning restore nullable`: Restores the nullable warning context to the project settings.
77+
- `#pragma warning safeonly nullable`: Sets the nullable warning context to **safeonly**.
78+
79+
The default nullable annotation and warning contexts are `disabled`. That decision means that your existing code compiles without changes and without generating any new warnings.
80+
81+
The differences between the `enabled` and `safeonly` nullable warning contexts are warnings for assigning a nullable reference to a non-nullable reference. The following assignment generates a warning in an `enabled` warning context, but not a `safeonly` warning context. However, the second line, where `s` is dereferenced, generates a warning in a `safeonly` context:
82+
83+
```csharp
84+
string s = null; // warning when nullable warning context is enabled.
85+
var txt = s.ToString(); // warning when nullable warnings context is safeonly, or enabled.
86+
```
4687

47-
The default nullable context is `disabled`. That decision means that your existing code compiles without changes and without generating any new warnings.
88+
### Nullable annotation context
4889

49-
The compiler uses the following rules in a disabled nullable context:
90+
The compiler uses the following rules in a disabled nullable annotation context:
5091

5192
- You can't declare nullable references in a disabled context.
5293
- All reference variables may be assigned to null.
@@ -55,25 +96,26 @@ The compiler uses the following rules in a disabled nullable context:
5596

5697
The behavior is the same as previous versions of C#.
5798

58-
The compiler uses the following rules in an enabled nullable context:
99+
The compiler uses the following rules in an enabled nullable annotation context:
59100

60101
- Any variable of a reference type is a **non-nullable reference**.
61102
- Any non-nullable reference may be dereferenced safely.
62103
- Any nullable reference type (noted by `?` after the type in the variable declaration) may be null. Static analysis determines if the value is known to be non-null when it is dereferenced. If not, the compiler warns you.
63104
- You can use the null-forgiving operator to declare that a nullable reference isn't null.
64105

65-
A richer grammar is proposed for nullable contexts and will be available in future previews. For more information about nullable contexts, see the [nullable reference specification](https://github.com/dotnet/csharplang/blob/master/proposals/nullable-reference-types-specification.md#nullable-contexts) draft.
106+
In an enabled nullable annotation context, the `?` character appended to a reference type declares a **nullable reference type**. The **null forgiveness operator** (`!`) may be appended to an expression to declare that the expression isn't null.
66107

67-
## Null states of nullable references
108+
## Nullable warning context
68109

69-
The compiler uses static analysis to determine the **null state** of any nullable reference. The null state is either **not null** or **maybe null**. If you dereference a nullable reference when the compiler has determined it's **maybe null**, the compiler warns you. The state of a nullable reference is **maybe null** unless the compiler can determine one of two conditions:
110+
The nullable warning context is distinct from the nullable annotation context. Warnings can be enabled even when the new annotations are disabled. The compiler uses static flow analysis to determine the **null state** of any reference. The null state is either **not null** or **maybe null** when the *nullable warning context* isn't **disabled**. If you dereference a reference when the compiler has determined it's **maybe null**, the compiler warns you. The state of a reference is **maybe null** unless the compiler can determine one of two conditions:
70111

71112
1. The variable has been definitely assigned to a non-null value.
72-
1. The variable has been checked against null before de-referencing it.
113+
1. The variable or expression has been checked against null before de-referencing it.
73114

74-
The compiler enforces that non-nullable references may never be set to the null value. You must initialize them to a non-null value. If you don't, the compiler warns that a non-nullable reference wasn't initialized. The compiler also warns you whenever you assign a non-nullable reference to a nullable reference that **may be null**. That implies you can only assign a non-nullable reference to a nullable reference if that nullable reference is **not null**.
115+
The compiler generates warnings whenever you dereference a variable or expression in a **maybe null** state when the nullable warning context is `enabled` or `safeonly`. Furthermore, warnings are generated when a **maybe null** variable or expression is assigned to a nonnullable reference type when the nullable annotation context is `enabled`.
75116

76117
## Learn more
77118

78119
- [Draft Nullable reference specification](https://github.com/dotnet/csharplang/blob/master/proposals/nullable-reference-types-specification.md)
79120
- [Intro to nullable references tutorial](tutorials/nullable-reference-types.md)
121+
- [Migrate an existing codebase to nullable references](tutorials/upgrade-to-nullable-references.md)

0 commit comments

Comments
 (0)