How to treat ALL C# 8 nullable reference warnings as errors?
Solution 1
It is now possible to treat all nullable-related warnings as errors without explicitly specifying them all. To achieve this, you have to set <WarningsAsErrors>Nullable</WarningsAsErrors>
in your *.csproj file [source].
Full example:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<Nullable>enable</Nullable>
<WarningsAsErrors>Nullable</WarningsAsErrors>
</PropertyGroup>
</Project>
Solution 2
I would suggest to use this solution. It mentions all 3 errors and IMHO better solution
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<LangVersion>8.0</LangVersion>
<WarningsAsErrors>CS8600;CS8602;CS8603</WarningsAsErrors>
</PropertyGroup>
</Project>
Update:
We have this list now:
<WarningsAsErrors>CS8600;CS8601;CS8602;CS8603;CS8613;CS8625;CS8629;CS8614;CS8619;CS8633</WarningsAsErrors>
Update 2021-04:
We have this list now:
<WarningsAsErrors>CS8600;CS8601;CS8602;CS8603;CS8604;CS8613;CS8614;CS8619;CS8620;CS8622;CS8625;CS8629;CS8633,CS8767</WarningsAsErrors>
Solution 3
The problem was that the .editorconfig
file was overriding the Visual Studio setting to treat all warnings as errors with many lines like:
dotnet_diagnostic.CS8602.severity = warning
This forces CS8602 to be a warning.
How this happened: In a previous attempt at turning all nullable reference warnings into errors, I set many of them as errors in the editor config. In that, I discovered both that there were a ton of different warning numbers and that my codebase wasn't ready for them to be errors throughout the entire solution. So I set them to "warning" in the editor config because I didn't want to lose the list of warnings I had found. Then later, having forgotten all about that, I decided to turn on treat warnings as errors on a project by project basis.
Comments
-
Jeff Walker Code Ranger about 2 years
Using Visual Studio 2019 v16.3.2 with a .NET Core 3.0 project set to C# 8 and nullable reference types enabled.
<PropertyGroup> <TargetFramework>netcoreapp3.0</TargetFramework> <LangVersion>8.0</LangVersion> <Nullable>enable</Nullable> </PropertyGroup>
If I set it to treat all warnings as errors:
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <WarningsAsErrors />
It reports other warnings as errors. For example,
CS0168 The variable 'x' is declared but never used
is reported as an error. But all the nullable reference warnings are still reported as warnings. For example,CS8600 Converting null literal or possible null value to non-nullable type.
is still reported as a warning.How do I treat all nullable reference warnings as errors?
Note: even setting CS8600 specifically to be treated as an error doesn't cause it to be reported as an error. If that worked, it still wouldn't help with treating them all as errors because there are so many.
Edit: setting specific warnings to be treated as errors puts
<WarningsAsErrors>CS8600;CS8602;CS8603</WarningsAsErrors>
in the csproj and doesn't work. -
Jeff Walker Code Ranger over 4 years@MindSwipe No, other C# 8 features work fine. What gave you that idea? I never said that.
-
officer about 4 yearsRegarding your update: maybe
CS8618 C# Non-nullable property is uninitialized. Consider declaring the property as nullable.
might also be relevant to include. -
SerjG about 3 yearsbe careful. You will have to treat all not null properties with fake init
= null!;
Is there any way to add all and then exclude certain ones? -
SerjG about 3 years@officer this is what we are trying to avoid for all DTOs, models and other classes which will never be created with
new()
-
officer about 3 yearsThe question is explicitly about treating all nullable warnings as errors.
-
officer about 3 years@SerjG Other than that, my approach to introduce the nullable feature in existing code bases is to use the
#nullable enable
pragma for new/changed files. The other way around could be to globally enable it but opt-out for your special files with#nullable disable
. -
SerjG about 3 yearsNot sure how can it help with all that annoying places with ` = null!`
-
Christoph over 2 years@SerjG: I don't get it: Why would you have such properties? Either it is nullable or it is not and then it must be initialized in some way, either directly in its declaration or in the constructor or by a helper method called in the constructor (use attribute
MemberNotNull
) or it gets initialized through a lazy getter and then the property is non-nullable with attributeAllowNull
for the setter (but declared on the property) if it is allowed to clear the cached value and have it recreated by the next getter call. -
Christoph over 2 years@SerjG: Or you have properties where it is invalid to assign
null
which do not need to be initialized, then that would be a nullable property with attributeDisallowNull
for the setter (but declared on the property). -
SerjG over 2 years@Christoph we have a lot of JSON models which will ne initialized one deserialized. And yes, we are too lazy to create .ctors.
-
Christoph over 2 years@SerjG: But would that not be a classic usage of nullable reference types? Each property may be null, may have been serialized as null, may not have been serialized because the model changed after the serialization or the JSON data was changed manually etc.? I personally would make all value- and reference types of DTO properties nullable (the nullalbe value types only of new or private interfaces as it breaks the existing contract), and the method receiving the DTO validates whether all mandatory properties are initialized and contain sensible values...
-
SerjG over 2 years@Christoph no it's not. We mark with ? properties which can be deserialized as null. Validation is not enough to make analyzer think that value is presented. So we have to use ! or transform to some other object which has not null properties. Both ways are annoying
-
Christoph over 2 years@SerjG: But that concept does not work imho: What if a non-nullable reference property is not included in the serialized JSON for whatever reason? It becomes
null
when deserialized and is passed on asnull
but you guarantee it is non-null
in your contract. -
SerjG over 2 years@Christoph yes. It's a trade-off between a lot of null checks and correct nullability usage. Also we have validation for required properties and should not work with invalid objects