Open RikkiGibson opened 3 years ago
The feature is now implemented and merged into the compiler.
Could this be extended to work in switch expressions, a natural evolution from conditional expressions?
// Already works
public string ValidationMessage => validationResult?.IsError(out var errorMessage) is true ? errorMessage : null
// But this does not
public string ValidationMessage => validationResult?.IsError(out var errorMessage) switch
{
// ❌ CS0165 Use of unassigned local variable 'errorMessage'
// ↓↓↓↓↓↓↓↓↓↓↓↓
true => errorMessage,
false => $"The backup path has been validated by {instanceName}",
_ => "Checking the backup path..."
};
Improved Definite Assignment Analysis
Summary
Definite assignment analysis as specified has a few gaps which have caused users inconvenience. In particular, scenarios involving comparison to boolean constants, conditional-access, and null coalescing.
Related discussions and issues
csharplang discussion of this proposal: #4240
Probably a dozen or so user reports can be found via this or similar queries (i.e. search for "definite assignment" instead of "CS0165", or search in csharplang). https://github.com/dotnet/roslyn/issues?q=is%3Aclosed+is%3Aissue+label%3A%22Resolution-By+Design%22+cs0165
I have included related issues in the scenarios below to give a sense of the relative impact of each scenario.
Scenarios
As a point of reference, let's start with a well-known "happy case" that does work in definite assignment and in nullable.
Comparison to bool constant
if ((c != null && c.M(out object obj2)) is true) { obj2.ToString(); // undesired error }
Conditional access coalesced to a bool constant
This scenario is very similar to the previous one. This is also supported in nullable but not in definite assignment.
Conditional expressions where one arm is a bool constant
It's worth pointing out that we already have special behavior for when the condition expression is constant (i.e.
true ? a : b
). We just unconditionally visit the arm indicated by the constant condition and ignore the other arm.Also note that we haven't handled this scenario in nullable.
Specification
The specification has moved to https://github.com/dotnet/csharplang/blob/master/proposals/improved-definite-assignment.md
Drawbacks
It feels odd to have the analysis "reach down" and have special recognition of conditional accesses, when typically flow analysis state is supposed to propagate upward. We are concerned about how a solution like this could intersect painfully with possible future language features that do null checks.
Alternatives
Two alternatives to this proposal:
Unresolved questions
[ ] There are impacts on switch expressions that should be specified: https://github.com/dotnet/csharplang/discussions/4240#discussioncomment-343395
[ ] It could be useful to also allow certain expressions using lifted relational operators to benefit: https://github.com/dotnet/roslyn/pull/52425#discussion_r610938838
Design meetings
https://github.com/dotnet/csharplang/discussions/4243