@@ -855,6 +855,8 @@ A compiler is not required to perform any static analysis nor is it required to
855
855
856
856
**The remainder of this subclause is conditionally normative .**
857
857
858
+ #### §flow-analysis Flow analysis
859
+
858
860
A compiler that generates diagnostic warnings conforms to these rules .
859
861
860
862
Every expression has one of three ***null state ***s :
@@ -921,10 +923,10 @@ A compiler can update the null state of a variable as part of its analysis.
921
923
> int length = p .Length ; // Warning: p is maybe null
922
924
>
923
925
> string s = p ; // No warning. p is not null
924
- >
926
+ >
925
927
> if (s != null )
926
928
> {
927
- > int l2 = s .Length ; // No warning. s is not null
929
+ > int l2 = s .Length ; // No warning. s is not null
928
930
> }
929
931
> int l3 = s .Length ; // Warning. s is maybe null
930
932
> }
@@ -994,13 +996,13 @@ A compiler can treat a property ([§15.7](classes.md#157-properties)) as either
994
996
> {
995
997
> get
996
998
> {
997
- > string tmp = _field ;
998
- > _field = null ;
999
- > return tmp ;
999
+ > string tmp = _field ;
1000
+ > _field = null ;
1001
+ > return tmp ;
1000
1002
> }
1001
1003
> set
1002
1004
> {
1003
- > _field = value ;
1005
+ > _field = value ;
1004
1006
> }
1005
1007
> }
1006
1008
>
@@ -1027,7 +1029,7 @@ A compiler may use any expression that dereferences a variable, property, or eve
1027
1029
> public class C
1028
1030
> {
1029
1031
> private C ? child ;
1030
- >
1032
+ >
1031
1033
> public void M ()
1032
1034
> {
1033
1035
> _ = child .child .child ; // Warning. Dereference possible null value
@@ -1038,4 +1040,125 @@ A compiler may use any expression that dereferences a variable, property, or eve
1038
1040
>
1039
1041
> * end example *
1040
1042
1043
+ #### §type-conversions Type conversions
1044
+
1045
+ A compiler that generates diagnostic warnings conforms to these rules .
1046
+
1047
+ > * 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 )). * end note *
1048
+
1049
+ A compiler may issue a warning when nullability annotations differ between two types , either top - level or nested , when the conversion is narrowing .
1050
+
1051
+ > *Example *: Types differing in top - level annotations
1052
+ >
1053
+ > < ! -- Example : {template : " code-in-class-lib" , name : " TopLevelNullabilityConversionWarnings" , ignoredWarnings : [" CS8600" ]} -- >
1054
+ > ```csharp
1055
+ > #nullable enable
1056
+ > public class C
1057
+ > {
1058
+ > public void M1 (string p )
1059
+ > {
1060
+ > _ = (string ?)p ; // No warning, widening
1061
+ > }
1062
+ >
1063
+ > public void M2 (string ? p )
1064
+ > {
1065
+ > _ = (string )p ; // Warning, narrowing
1066
+ > _ = (string )p ! ; // No warning, suppressed
1067
+ > }
1068
+ > }
1069
+ > ```
1070
+ >
1071
+ > * end example *
1072
+ < ! -- markdownlint - disable MD028 -- >
1073
+
1074
+ < ! -- markdownlint - enable MD028 -- >
1075
+ > * Example * : Types differing in nested nullability annotations
1076
+ >
1077
+ > < ! -- Example : {template : " code-in-class-lib" , name : " NestedNullabilityConversionWarnings" , ignoredWarnings : [" CS8619" ]} -- >
1078
+ > ```csharp
1079
+ > #nullable enable
1080
+ > public class C
1081
+ > {
1082
+ > public void M1 ((string , string ) p )
1083
+ > {
1084
+ > _ = ((string ?, string ?))p ; // No warning, widening
1085
+ > }
1086
+ >
1087
+ > public void M2 ((string ? , string ? ) p )
1088
+ > {
1089
+ > _ = ((string , string ))p ; // Warning, narrowing
1090
+ > _ = ((string , string ))p ! ; // No warning, suppressed
1091
+ > }
1092
+ > }
1093
+ > ```
1094
+ >
1095
+ > * end example *
1096
+
1097
+ 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 (§17 . 6 ) in determining whether to issue a warning for type conversions.
1098
+
1099
+ > <!-- Example: {template:"code-in-class-lib", name:"NullVariance", ignoredWarnings:["CS8619"]} -- >
1100
+ > ```csharp
1101
+ > #nullable enable
1102
+ > public class C
1103
+ > {
1104
+ > public void M1 (IEnumerable <string > p )
1105
+ > {
1106
+ > IEnumerable < string ? > v1 = p ; // No warning
1107
+ > }
1108
+ >
1109
+ > public void M2 (IEnumerable <string ?> p )
1110
+ > {
1111
+ > IEnumerable < string > v1 = p ; // Warning
1112
+ > IEnumerable < string > v2 = p ! ; // No warning
1113
+ > }
1114
+ >
1115
+ > public void M3 (Action <string ?> p )
1116
+ > {
1117
+ > Action < string > v1 = p ; // No warning
1118
+ > }
1119
+ >
1120
+ > public void M4 (Action <string > p )
1121
+ > {
1122
+ > Action < string ? > v1 = p ; // Warning
1123
+ > Action < string ? > v2 = p ! ; // No warning
1124
+ > }
1125
+ >
1126
+ > public void M5 (string [] p )
1127
+ > {
1128
+ > string ? [] v1 = p ; // No warning
1129
+ > }
1130
+ >
1131
+ > public void M6 (string ?[] p )
1132
+ > {
1133
+ > string [] v1 = p ; // Warning
1134
+ > string [] v2 = p ! ; // No warning
1135
+ > }
1136
+ > }
1137
+ > ```
1138
+ >
1139
+ > * end example *
1140
+
1141
+ A compiler may issue a warning when nullability differs in either direction in types which do not permit a variant conversion .
1142
+
1143
+ > < ! -- Example : {template : " code-in-class-lib" , name : " NullInvariance" , ignoredWarnings : [" CS8619" ]} -- >
1144
+ > ```csharp
1145
+ > #nullable enable
1146
+ > public class C
1147
+ > {
1148
+ > public void M1 (List < string > p )
1149
+ > {
1150
+ > List < string ? > v1 = p ; // Warning
1151
+ > List < string ? > v2 = p ! ; // No warning
1152
+ > }
1153
+ >
1154
+ > public void M2 (List < string ? > p )
1155
+ > {
1156
+ > List < string > v1 = p ; // Warning
1157
+ > List < string > v2 = p ! ; // No warning
1158
+ > }
1159
+ > }
1160
+ > ```
1161
+ >
1162
+ > * end example *
1163
+
1041
1164
*** End of conditionally normative text ***
0 commit comments