Open
Description
Championed issue: dotnet/csharplang#8677
Speclet: https://github.com/dotnet/csharplang/blob/main/proposals/null-conditional-assignment.md
Label:
Feature - Null Conditional Assignment
Feature branch: https://github.com/dotnet/roslyn/tree/features/null-conditional-assignment
Compiler
- language version
- parsing / syntax model does not depend on language version (
NullConditionalAssignmentParsingTests
) - member and element assignment (
LangVersion_*
)
- parsing / syntax model does not depend on language version (
- compound assignment: (
LangVersion_03
)- parsing (
NullConditionalAssignmentParsingTests.VariousAssignmentKinds_LeftMemberAccess
) - arithmetic operators:
+=
, etc. (CompoundAssignment_01
) - logical operators:
|=
, etc. - shift operators:
<<=
, etc.
- parsing (
- increment, decrement (disallowed):
a?.B++
,--a?.B
(IncrementDecrement_01
) - member kinds:
- field
- property
- event
- method
- null coalescing:
a?.B ??= c
(NullCoalescingAssignment_01
) - nested:
-
a?.b?.c = d
(PropertyAccessAssignment_Nested_01
) -
a?.b = c?.d = e?.f
(FieldAccessAssignment_Nested_03
) -
a?.b = c ?? d
(NullConditionalAssignmentParsingTests.NullCoalescing_LeftMemberAccess
)
-
- readonly member
- readonly indexer
-
struct
receiver (FieldAccessAssignment_StructReceiver_*
)- readonly member
-
ref
returning member (AssignRefReturningMethod_01
) - cases from Readonly setter calls on non-variables
- spec explicitly the limitations around structs
-
a?.B = c
whereB
isinit
property - inline array with conditional element assignment
- Expression trees (disallowed)
-
dynamic
receiver -
*s?.P = e
- use result:
(a?.B = c)?.ToString()
- member with reference type
- member with value type
- member with type parameter type: (
TypeParameter_*
)- unconstrained (disallowed)
-
struct
constraint -
class
constraint
- element assignment
- evaluation:
- receiver evaluated exactly once (
FieldAccessAssignment_Nested_03
) - RHS evaluated conditionally (
FieldAccessAssignment_Nested_03
) - element index evaluated conditionally
- member arguments evaluated conditionally
- using result (
FieldAccessAssignment_Nested_04
)
- receiver evaluated exactly once (
- ref assignment (disallowed):
a?.B = ref c
(RefAssignment_01
) - deconstruction assignment (disallowed):
(a?.B, c?.D) = (x, y)
(DeconstructionLeft
) - await:
(await a)?.B = c
- definite assignment
- receiver not definitely assigned (
DefiniteAssignment_01
) - variable only assigned or used in RHS
- variable only assigned or used in member arguments
- receiver not definitely assigned (
- nullable analysis
- receiver maybe null after
a?.B = c
(NullableAnalysis_01
) - receiver and member not null after checking result (
NullableAnalysis_01
) -
a?.B = a.C;
should not warn fora.C
- suppression operator:
a?.B! = c
- receiver maybe null after
-
Semantic model(no changes) -
(no changes)IOperation
- CFG (
ConditionalAccessFlow_06
,_07
)- null-coalescing assignment:
??=
(ensure assignment in correct branch of CFG) - conditional receiver:
(c ? a : b)?.D = e
- null-coalescing assignment:
-
Public API(no changes)
Productivity
- formatting
- Quick info for member
- Go to Definition for member
- Refactoring from existing code
- Generate member for
a?.b = c
Support generate method in null-conditional-assignment #77526