Skip to content

Commit da6c48d

Browse files
committed
Nullability examples: conversions
1 parent ed6cd81 commit da6c48d

File tree

1 file changed

+121
-0
lines changed

1 file changed

+121
-0
lines changed

Diff for: standard/types.md

+121
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,8 @@ A compiler is not required to perform any static analysis nor is it required to
859859
860860
**The remainder of this subclause is conditionally normative.**
861861
862+
#### 8.9.5.1 Flow analysis
863+
862864
A compiler that generates diagnostic warnings conforms to these rules.
863865
864866
Every expression has one of three ***null state***s:
@@ -1042,4 +1044,123 @@ A compiler may use any expression that dereferences a variable, property, or eve
10421044
>
10431045
> *end example*
10441046
1047+
#### 8.9.5.2 Type conversions
1048+
1049+
A compiler that generates diagnostic warnings conforms to these rules.
1050+
1051+
> *Note:* Differences in top-level or nested nullability annotations in types do not affect whether conversion between the types is permitted, since there is no semantic difference between a non-nullable reference type and its corresponding nullable type ([§8.9.1](types.md#891-general)).
1052+
1053+
A compiler may issue a warning when nullability annotations differ between two types, either top-level or nested, when the conversion is narrowing.
1054+
1055+
> *Example*: Types differing in top-level annotations
1056+
>
1057+
> <!-- Example: {template:"code-in-class-lib", name:"TopLevelNullabilityConversionWarnings"} -->
1058+
> ```csharp
1059+
> #nullable enable
1060+
> public class C
1061+
> {
1062+
> public void M1(string p)
1063+
> {
1064+
> _ = (string?)p; // No warning, widening
1065+
> }
1066+
>
1067+
> public void M2(string? p)
1068+
> {
1069+
> _ = (string)p; // Warning, narrowing
1070+
> _ = (string)p!; // No warning, suppressed
1071+
> }
1072+
> }
1073+
> ```
1074+
>
1075+
> *end example*
1076+
1077+
> *Example*: Types differing in nested nullability annotations
1078+
>
1079+
> <!-- Example: {template:"code-in-class-lib", name:"NestedNullabilityConversionWarnings"} -->
1080+
> ```csharp
1081+
> #nullable enable
1082+
> public class C
1083+
> {
1084+
> public void M1((string, string) p)
1085+
> {
1086+
> _ = ((string?, string?))p; // No warning, widening
1087+
> }
1088+
>
1089+
> public void M2((string?, string?) p)
1090+
> {
1091+
> _ = ((string, string))p; // Warning, narrowing
1092+
> _ = ((string, string))p!; // No warning, suppressed
1093+
> }
1094+
> }
1095+
> ```
1096+
>
1097+
> *end example*
1098+
1099+
A compiler may follow rules for interface variance ([§18.2.3.3](interfaces.md#18233-variance-conversion)), delegate variance ([§20.4](delegates.md#204-delegate-compatibility)), and array covariance ([§1.7.6](arrays.md#176-array-covariance)) in determining whether to issue a warning for type conversions.
1100+
1101+
> <!-- Example: {template:"code-in-class-lib", name:"NullVariance"} -->
1102+
> ```csharp
1103+
> #nullable enable
1104+
> public class C
1105+
> {
1106+
> public void M1(IEnumerable<string> p)
1107+
> {
1108+
> IEnumerable<string?> v1 = p; // No warning
1109+
> }
1110+
>
1111+
> public void M2(IEnumerable<string?> p)
1112+
> {
1113+
> IEnumerable<string> v1 = p; // Warning
1114+
> IEnumerable<string> v2 = p!; // No warning
1115+
> }
1116+
>
1117+
> public void M3(Action<string?> p)
1118+
> {
1119+
> Action<string> v1 = p; // No warning
1120+
> }
1121+
>
1122+
> public void M4(Action<string> p)
1123+
> {
1124+
> Action<string?> v1 = p; // Warning
1125+
> Action<string?> v2 = p!; // No warning
1126+
> }
1127+
>
1128+
> public void M5(string[] p)
1129+
> {
1130+
> string?[] v1 = p; // No warning
1131+
> }
1132+
>
1133+
> public void M6(string?[] p)
1134+
> {
1135+
> string[] v1 = p; // Warning
1136+
> string[] v2 = p!; // No warning
1137+
> }
1138+
> }
1139+
> ```
1140+
>
1141+
> *end example*
1142+
1143+
A compiler may issue a warning when nullability differs in either direction in types which do not permit a variant conversion.
1144+
1145+
> <!-- Example: {template:"code-in-class-lib", name:"NullInvariance"} -->
1146+
> ```csharp
1147+
> #nullable enable
1148+
> public class C
1149+
> {
1150+
> public void M1(List<string> p)
1151+
> {
1152+
> List<string?> v1 = p; // Warning
1153+
> List<string?> v1 = p!; // No Warning
1154+
> }
1155+
>
1156+
> public void M2(List<string?> p)
1157+
> {
1158+
> List<string> v1 = p; // Warning
1159+
> List<string> v1 = p!; // No Warning
1160+
> }
1161+
> }
1162+
> ```
1163+
>
1164+
> *end example*
1165+
10451166
***End of conditionally normative text***

0 commit comments

Comments
 (0)