-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add note about interactions in operators #18124
Add note about interactions in operators #18124
Conversation
Fixes dotnet#17988. See dotnet#17988 (comment) The null conditional operators and null forgiving operators interact in interesting ways. Add notes on both pages to explain those interactions.
docs/csharp/language-reference/operators/member-access-operators.md
Outdated
Show resolved
Hide resolved
docs/csharp/language-reference/operators/member-access-operators.md
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After all those discussions, I wouldn't call that behavior "unexpected". (That is, the docs shouldn't use subjective language.)
@@ -132,6 +132,9 @@ In the preceding example, if you don't use the `??` operator, `numbers?.Length < | |||
|
|||
The null-conditional member access operator `?.` is also known as the Elvis operator. | |||
|
|||
> [!NOTE] | |||
> The null-conditional operators can interact with the [null-forgiving operator](null-forgiving.md) in unexpected ways. In C# 8 the expression `x?.y!.z` is parsed as `(x?.y)!.z`. Due to this interpretation `z` is evaluated even if `x` is null, which may result in a <xref:System.NullReferenceException>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
> The null-conditional operators can interact with the [null-forgiving operator](null-forgiving.md) in unexpected ways. In C# 8 the expression `x?.y!.z` is parsed as `(x?.y)!.z`. Due to this interpretation `z` is evaluated even if `x` is null, which may result in a <xref:System.NullReferenceException>. | |
> In C# 8.0, a null-conditional expression doesn't include the [null-forgiving operator](null-forgiving.md). That is, expression `x?.y!.z` is parsed as `(x?.y)!.z`. Due to this interpretation, `z` is evaluated even if `x` is `null`, which may result in a <xref:System.NullReferenceException>. |
@@ -13,6 +13,9 @@ Available in C# 8.0 and later, the unary postfix `!` operator is the null-forgiv | |||
|
|||
The null-forgiving operator has no effect at run time. It only affects the compiler's static flow analysis by changing the null state of the expression. At run time, expression `x!` evaluates to the result of the underlying expression `x`. | |||
|
|||
> [!NOTE] | |||
> The null-forgiving operator can interact with the [null-conditional operators](member-access-operators.md#null-conditional-operators--and-) in unexpected ways. In C# 8 the expression `x?.y!.z` is parsed as `(x?.y)!.z`. Due to this interpretation `z` is evaluated even if `x` is null, which may result in a <xref:System.NullReferenceException>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
> The null-forgiving operator can interact with the [null-conditional operators](member-access-operators.md#null-conditional-operators--and-) in unexpected ways. In C# 8 the expression `x?.y!.z` is parsed as `(x?.y)!.z`. Due to this interpretation `z` is evaluated even if `x` is null, which may result in a <xref:System.NullReferenceException>. | |
> In C# 8.0, a [null-conditional](member-access-operators.md#null-conditional-operators--and-) expression doesn't include the null-forgiving operator. That is, expression `x?.y!.z` is parsed as `(x?.y)!.z`. Due to this interpretation, `z` is evaluated even if `x` is `null`, which may result in a <xref:System.NullReferenceException>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point @pkulikov I made some edits, but I did leave the word "unexpected" in. In this instance, it's appropriate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@BillWagner thanks, then I have two nit-picks:
- Should "can interact" be "interacts"? As "can interact" suggests that it doesn't interact always like that
- Should "unexpected ways" be "unexpected way"?
@@ -132,6 +132,9 @@ In the preceding example, if you don't use the `??` operator, `numbers?.Length < | |||
|
|||
The null-conditional member access operator `?.` is also known as the Elvis operator. | |||
|
|||
> [!NOTE] | |||
> In C# 8, the null-conditional operators interacts with the [null-forgiving operator](null-forgiving.md) in an unexpected way. For example, the expression `x?.y!.z` is parsed as `(x?.y)!.z`. Due to this interpretation, `z` is evaluated even if `x` is `null`, which may result in a <xref:System.NullReferenceException>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@BillWagner Sorry, I did not look at the last commit yesterday and a grammar error crept in: "operators interacts". Also I rather agree with @pkulikov's comment:
After all those discussions, I wouldn't call that behavior "unexpected". (That is, the docs shouldn't use subjective language.)
I would prefer a neutral description like this:
In C# 8, the null-forgiving operator terminates the list of preceding null-conditional operations. For example, the expression
x?.y!.z
is parsed as(x?.y)!.z
. Due to this interpretation,z
is evaluated even ifx
isnull
, which may result in a xref:System.NullReferenceException.
I changed only the first sentence to describe "unexpected interaction" in more precise words. If you consider that an improvement, please let me know if I should create a PR for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @AntonLapounov I like that improved wording. I'll watch for a PR.
@@ -13,6 +13,9 @@ Available in C# 8.0 and later, the unary postfix `!` operator is the null-forgiv | |||
|
|||
The null-forgiving operator has no effect at run time. It only affects the compiler's static flow analysis by changing the null state of the expression. At run time, expression `x!` evaluates to the result of the underlying expression `x`. | |||
|
|||
> [!NOTE] | |||
> In C# 8 the null-forgiving operator interacts with the [null-conditional operators](member-access-operators.md#null-conditional-operators--and-) in an unexpected way. The expression `x?.y!.z` is parsed as `(x?.y)!.z`. Due to this interpretation `z` is evaluated even if `x` is `null`, which may result in a <xref:System.NullReferenceException>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know commas are frequently optional in English. Comparing to the previous note, this note misses commas after "In C# 8" and "Due to this interpretation". It also lost the "For example" part. Not sure if it was intentional.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was not intentional. If you want to fix this in the same PR (along with the updated wording), I'll merge it.
Fixes #17988. See #17988 (comment)
The null conditional operators and null forgiving operators interact in interesting ways. Add notes on both pages to explain those interactions.