Skip to content
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

Merged
merged 5 commits into from
Apr 29, 2020

Conversation

BillWagner
Copy link
Member

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.

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.
Copy link
Contributor

@pkulikov pkulikov left a 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>.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
> 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>.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
> 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>.

Copy link
Member Author

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.

Copy link
Contributor

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"?

@BillWagner BillWagner merged commit 8c09903 into dotnet:master Apr 29, 2020
@BillWagner BillWagner deleted the null-forgiving-coalescing branch April 29, 2020 15:27
@@ -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>.
Copy link
Member

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 if x is null, 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.

Copy link
Member Author

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>.
Copy link
Member

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.

Copy link
Member Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

null-forgiving operator *can have* effect at run time
3 participants