@@ -859,6 +859,8 @@ A compiler is not required to perform any static analysis nor is it required to
859
859
860
860
**The remainder of this subclause is conditionally normative .**
861
861
862
+ #### 8.9.5.1 Flow analysis
863
+
862
864
A compiler that generates diagnostic warnings conforms to these rules .
863
865
864
866
Every expression has one of three ***null state ***s :
@@ -1042,4 +1044,78 @@ A compiler may use any expression that dereferences a variable, property, or eve
1042
1044
>
1043
1045
> * end example *
1044
1046
1047
+ #### 8.9.5.2 Type conversions
1048
+
1049
+ For the purpose of determining whether a conversion is * permitted *, a compiler must consider every nullable - annotated type to be equivalent to its unannotated version . The compiler may however issue warnings if the annotations of the types are not compatible .
1050
+
1051
+ (examples : `List < string > ` to `IEnumerable < object ? > `, or `List < string ? > ? ` to `IEnumerable < object > `, .. .)
1052
+
1053
+ 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.
1054
+ (Do we need to list each type here? E.g. tuple types...)
1055
+
1056
+ > < ! -- Example : {template : " code-in-class-lib" , name : " NullVariance" } -- >
1057
+ > ```csharp
1058
+ > #nullable enable
1059
+ > public class C
1060
+ > {
1061
+ > public void M1 (IEnumerable <string > p )
1062
+ > {
1063
+ > IEnumerable < string ? > v1 = p ; // No warning
1064
+ > }
1065
+ >
1066
+ > public void M2 (IEnumerable <string ?> p )
1067
+ > {
1068
+ > IEnumerable < string > v1 = p ; // Warning
1069
+ > IEnumerable < string > v2 = p ! ; // No warning
1070
+ > }
1071
+ >
1072
+ > public void M3 (Action <string ?> p )
1073
+ > {
1074
+ > Action < string > v1 = p ; // No warning
1075
+ > }
1076
+ >
1077
+ > public void M4 (Action <string > p )
1078
+ > {
1079
+ > Action < string ? > v1 = p ; // Warning
1080
+ > Action < string ? > v2 = p ! ; // No warning
1081
+ > }
1082
+ >
1083
+ > public void M5 (string [] p )
1084
+ > {
1085
+ > string ? [] v1 = p ; // No warning
1086
+ > }
1087
+ >
1088
+ > public void M6 (string ?[] p )
1089
+ > {
1090
+ > string [] v1 = p ; // Warning
1091
+ > string [] v2 = p ! ; // No warning
1092
+ > }
1093
+ > }
1094
+ > ```
1095
+ >
1096
+ > * end example *
1097
+
1098
+ Types that are invariant likewise may produce a warning when the conversion differs only in the nullability of type arguments .
1099
+
1100
+ > < ! -- Example : {template : " code-in-class-lib" , name : " NullInvariance" } -- >
1101
+ > ```csharp
1102
+ > #nullable enable
1103
+ > public class C
1104
+ > {
1105
+ > public void M1 (List <string > p )
1106
+ > {
1107
+ > List < string ? > v1 = p ; // Warning
1108
+ > List < string ? > v1 = p ! ; // No Warning
1109
+ > }
1110
+ >
1111
+ > public void M2 (List <string ?> p )
1112
+ > {
1113
+ > List < string > v1 = p ; // Warning
1114
+ > List < string > v1 = p ! ; // No Warning
1115
+ > }
1116
+ > }
1117
+ > ```
1118
+ >
1119
+ > * end example *
1120
+
1045
1121
*** End of conditionally normative text ***
0 commit comments