I have a nullable property like so:
string? MyString
{
get { ... }
init
{
if (value is null)
return;
...
}
}
I don't like the guard against null's in the init
, and would prefer that the compiler enforce the condition:
string? MyString
{
get { ... }
}
string MyString
{
init { ... }
}
The compiler doesn't like this. The closest I can get is with the DisallowNullAttribute:
[DisallowNull]
string? MyString
{
get { ... }
init
{
if (value is null)
return;
...
}
}
This only provides a warning, so the guard is still necessary.
Is there a better way to achieve what I want?
I have a nullable property like so:
string? MyString
{
get { ... }
init
{
if (value is null)
return;
...
}
}
I don't like the guard against null's in the init
, and would prefer that the compiler enforce the condition:
string? MyString
{
get { ... }
}
string MyString
{
init { ... }
}
The compiler doesn't like this. The closest I can get is with the DisallowNullAttribute:
[DisallowNull]
string? MyString
{
get { ... }
init
{
if (value is null)
return;
...
}
}
This only provides a warning, so the guard is still necessary.
Is there a better way to achieve what I want?
The closest I can get is with the
DisallowNullAttribute
: This only provides a warning, so the guard is still necessary.
In terms of compiler's null-state static analysis DisallowNullAttribute
is the answer (as the Preconditions: AllowNull
and DisallowNull
section of the docs states).
To "fix" the "only warnings" problem you can use several options:
Enable the TreatWarningsAsErrors
option
<PropertyGroup>
<TreatWarningsAsErrors/>
</PropertyGroup>
Use <WarningsAsErrors>Nullable</WarningsAsErrors>
:
<PropertyGroup>
<WarningsAsErrors>Nullable</WarningsAsErrors>
</PropertyGroup>
Use concrete diagnostic (full list) for more granular control for example via editor config. For example:
[*.cs]
dotnet_diagnostic.CS8601.severity = error
dotnet_diagnostic.CS8602.severity = error
dotnet_diagnostic.CS8625.severity = error
Note that those are compiler checks which can still be "overriden" via the null-forgiving operator or by (temporary) disabling nullable context (if we don't dive into other "more complex" options like deserialization or reflection):
var myClass = new MyClass
{
MyString = null! // NO COMPILER ERROR DESPITE SETTINGS!
};
class MyClass
{
[DisallowNull]
public string? MyString // sample implementation to ignore
{
get => "1";
init => Console.WriteLine(value);
}
}
So if you want the most foolproof code then you need to keep the check.
null
? – Serg Commented Jan 9 at 18:14required
keyword). The purpose is to ensure that users of the property do not accidentally assign the property a null value and then think that the property has been set. This ensures stronger compile-time guarantees and reduces errors. – onbeben Commented Jan 9 at 18:30null
value by default (and user can check that value via theget
-ter), but you want to prevent user from explicitly initializing this property withnull
value? And how about the cloning/mapping scenarios when we just transfer data from the one object to the new one property-by-property? Is it ok that we will need to handle this specific property in very specific way? – Serg Commented Jan 9 at 18:37