Skip to content

Enable C# 8 Nullable Reference Types#259

Merged
Turnerj merged 12 commits intomainfrom
enable-nullable-reference-types
Mar 20, 2021
Merged

Enable C# 8 Nullable Reference Types#259
Turnerj merged 12 commits intomainfrom
enable-nullable-reference-types

Conversation

@RehanSaeed
Copy link
Copy Markdown
Owner

Fixes #127

@RehanSaeed RehanSaeed added enhancement Issues describing an enhancement or pull requests adding an enhancement. minor Pull requests requiring a minor version update according to semantic versioning. labels Mar 15, 2021
@RehanSaeed RehanSaeed requested a review from Turnerj March 15, 2021 11:03
@RehanSaeed RehanSaeed changed the title Enable C# 8 nullable reference types Enable C# 8 Nullable Reference Types Mar 15, 2021
@RehanSaeed
Copy link
Copy Markdown
Owner Author

I spent some time starting this. I have fixed most issues (errors look worse than they are because the types can't be generated until the build is fixed) but there is some internal stuff that I'm unsure of. It seems that there are a lot of places where we are not handling potential nulls correctly.

@Turnerj Would you like to cast your eye over the last 10% of errors? Then I'll see if I can fix anything that's left.

@Turnerj
Copy link
Copy Markdown
Collaborator

Turnerj commented Mar 15, 2021

Yep, no problem!

}

try
if (Enum.TryParse(targetType, enumString, out result))
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Enum.TryParse instead of try/catch. This could also be in another PR.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Don't know why we didn't do this sooner!

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Exactly! Performance win too!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think I found out why - that method doesn't exist in .NET Standard 2.0 😣

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Perhaps we can write our own TryParse that supports old platforms? That would move the ugly #if out of this code and turn this into a one liner.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Done! Created an EnumHelper static class with a TryParse method that copies the signature for Enum.TryParse.

@Turnerj
Copy link
Copy Markdown
Collaborator

Turnerj commented Mar 16, 2021

Nullable references support for the tool is done. Will look into the other bits left for the various Values<> types and then a few more in the ValuesJsonConverter later tonight.

@Turnerj
Copy link
Copy Markdown
Collaborator

Turnerj commented Mar 16, 2021

Looks like all the nullability changes should be in now though am getting an error on .NET Standard 2.0 at the moment:

image

I think it is just Visual Studio being weird at the moment.

Comment on lines 312 to 320
#if NETSTANDARD2_0 || NET472 || NET461
try
{
result = Enum.Parse(targetType, enumString);
success = true;
}
catch (Exception)
#else
if (Enum.TryParse(targetType, enumString, out result))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This seemed like an OK compromise. Not a huge fan of using 3 targets like I am here though.

It did make me wonder, why do we target .NET 4.7.2 and .NET 4.6.1 directly when we also target .NET Standard 2.0?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I repeat this type of check here as well with my switched up way to generate a ToString for PropertyValueSpecification: 85dde5a#diff-4170f976c7ab6112252917fe8fa2c6a2ce7bed515547e0e42e11ea4d67402f9dR47-R51

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Unfortunately there are severe bugs in .NET 4.7.2 and .NET 4.6.1 full framework when targetting netstandard2.0. I haven't used full framework for years but have had issues raised to add full framework back in (it's surprising how many people still use it).

@Turnerj
Copy link
Copy Markdown
Collaborator

Turnerj commented Mar 17, 2021

What are your thoughts about disabling nullable reference types for our tests? Our tests are designed to check very specific conditions anyway and will fail on any exception. We might be just adding all the additional markup for it just for it to be mostly irrelevant.

Copy link
Copy Markdown
Owner Author

@RehanSaeed RehanSaeed left a comment

Choose a reason for hiding this comment

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

The tests I've enabled nullable for have mostly involved liberal use of ! and ? with the occasional switch to immutable types. So nothing too onerous. We don't have many changes to tests currently but not sure if that'll change once everything is converted. Agree that it did feel mostly irrelevant, although I did manage to make the odd improvement.

Overall, I've been surprised at how little code has had to change to my other repos (this one seems the most complex) and nullable seems to have only made a marginal improvement.

}

try
if (Enum.TryParse(targetType, enumString, out result))
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Perhaps we can write our own TryParse that supports old platforms? That would move the ugly #if out of this code and turn this into a one liner.

var book = JsonConvert.DeserializeObject<Book>(this.json, TestDefaults.DefaultJsonSerializerSettings);
var book = JsonConvert.DeserializeObject<Book>(this.json, TestDefaults.DefaultJsonSerializerSettings)!;

Assert.True(book.Author.HasValue);
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Apparently Assert.NotNull supports nullable reference types, so if you assert that and use it's return value, you can avoid the exclamation here.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Had a look but it doesn't seem to be the case - Assert.NotNull returns voids.

image

{
Assert.Equal(a.GetHashCode(), b?.GetHashCode());
Assert.NotNull(a);
Assert.Equal(a!.GetHashCode(), b?.GetHashCode());
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Same here about Assert.NotNull

@RehanSaeed
Copy link
Copy Markdown
Owner Author

Build is green!

@RehanSaeed
Copy link
Copy Markdown
Owner Author

LGTM, are we ready to merge?

@Turnerj
Copy link
Copy Markdown
Collaborator

Turnerj commented Mar 19, 2021

Yeah, I'm happy with it!

@Turnerj Turnerj merged commit 5c222d6 into main Mar 20, 2021
@Turnerj Turnerj deleted the enable-nullable-reference-types branch March 20, 2021 05:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Issues describing an enhancement or pull requests adding an enhancement. minor Pull requests requiring a minor version update according to semantic versioning.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add C# 8 Nullable Reference Types

2 participants