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

Update coding guidelines to avoid using as keyword for type casting #5309

Merged
merged 2 commits into from
Jul 18, 2023

Conversation

zivkan
Copy link
Member

@zivkan zivkan commented Jul 12, 2023

Bug

Fixes: N/A

Description

Update coding guidelines to avoid using as keyword for type casting, as it causes NullReferenceException to be thrown instead of InvalidCastException, making debugging much harder.

In the future, if we can enable nullable referene types throughout the repo, then the compiler will tell us that the code is not null safe. But enabling nullable everywhere takes a lot of effort to fix all the existing issues and annotating APIs. So, this coding guideline is a reminder for us to write better null safe code until we can have the compiler automate null safety for us.

PR Checklist

  • PR has a meaningful title no product change

  • PR has a linked issue.

  • Described changes

  • Tests

    • Automated tests added
    • OR
    • Test exception
    • OR
    • N/A
  • Documentation

    • Documentation PR or issue filled
    • OR
    • N/A

@zivkan zivkan requested a review from a team as a code owner July 12, 2023 11:39
@zivkan zivkan force-pushed the dev-zivkan-coding-guidelines-as-casting branch from 9947fd0 to 0190255 Compare July 12, 2023 11:46
Exceptions are allowed when multiple type names coming from different namespaces are available.
Exceptions are allowed when multiple type names coming from different namespaces are available.

1. Do not use `as` to cast types
Copy link
Member

Choose a reason for hiding this comment

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

While I agree that objectively, as casting is probably not necessary, this almost feels like one of those things that's too opinionated. I don't mind accepting it, but that was my first instict.

Copy link
Member Author

Choose a reason for hiding this comment

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

Just about everything in the coding guidelines is opinionated!

In cases where nulls are silently ignored, it can be a correctness issue. I'm thinking of something like var item = CurrentSelection as Package; if (item is not null) { DoSomething(item); } to handle the case when a button is clicked when no package is selected. If the type is wrong, customers will have selected an item, but nothing happens and the customer doesn't know why, and there are no errors to help us understand.

In cases of var item = CurrentSelection as Package; var name = item.Name; then a NullReferenceException is much harder to debug from telemetry compared to an InvalidCastException that tells use "Type1 cannot be cast to Type2".

So, I don't understand why this guideline would be less appropriate than most of the other opinionated guidelines in this document. Many others are nothing more than stylistic, this one actually reduces debugging complexity, hence increases productivity.

Copy link
Contributor

Choose a reason for hiding this comment

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

This guideline makes sense to me. My ask is that we keep an eye where this guideline has an unintended consequence and revisit the guideline if needed.

Copy link
Contributor

@donnie-msft donnie-msft left a comment

Choose a reason for hiding this comment

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

What if I don't want InvalidCastException to be thrown? If we nullable enable more of our code, will this help address the NREs?

@zivkan
Copy link
Member Author

zivkan commented Jul 13, 2023

What if I don't want InvalidCastException to be thrown?

Then handle it, like in my second "this is correct" snippet. How is a NullReferenceException any better? NREs are harder to debug, since they provide less information.

If we nullable enable more of our code, will this help address the NREs?

Yes, enabling nullable would tell the author that the code they're writing is not null safe. But in cases like DoMethod(value as SomeType) we'll only get correct nullable warnings if DoMethod is already annotated, which is why I've been starting at the bottom of the project dependency graph and trying to work my way up (but it takes a LOT of effort): https://github.com/NuGet/Client.Engineering/issues/2255

This is incorrect:

```cs
ListItem item = selectedItem as ListItem;
Copy link
Contributor

Choose a reason for hiding this comment

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

Roslyn has an analyzer, Remove unnecessary cast (IDE0004) that flags instances when a cast is unnecessary. Perhaps the first step we should take is to change the severity of this analyzer to 'error.' I suspect that we are performing type casting as a safety measure, even in cases where these casts are implicit from the compiler's perspective.

image

@aortiz-msft
Copy link
Contributor

Team Review: This is approved to be merged, but please update the PR description to show that this is a step we are taking before we turn on nullable checks on the codebase.

Copy link
Contributor

@donnie-msft donnie-msft left a comment

Choose a reason for hiding this comment

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

Thank you for steering the team towards better coding patterns!

```

```cs
if (obj is Type1 t1)
Copy link
Contributor

Choose a reason for hiding this comment

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

My understanding is this return/return/throw pattern is just an example, not a prescriptive pattern for all scenarios. With that understanding, I think it's worth trying and hopefully will help readibility.

@zivkan zivkan merged commit 2a02fee into dev Jul 18, 2023
@zivkan zivkan deleted the dev-zivkan-coding-guidelines-as-casting branch July 18, 2023 19:14
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.

6 participants