Skip to content

Instantly share code, notes, and snippets.

@usametov
Created April 20, 2021 15:34
Show Gist options
  • Save usametov/48901681f5367e5dc123d400fe4f55e6 to your computer and use it in GitHub Desktop.
Save usametov/48901681f5367e5dc123d400fe4f55e6 to your computer and use it in GitHub Desktop.
CSharp nullable types notes
// using the same syntax as for value types
string nonNullable = null; // compiler warning
string? nullable = null;
// here is breaking change in a new version of the language,
// the nullable reference types is the only feature of C# 8 that isn’t enabled by default
//look: before C# 8
string nullableString;
//now it looks the same, but semantic changed
// since C# 8
string nonNullableString;
// add this setting to the project file for that:
//<Nullable>enable</Nullable>
// In recent versions of Visual Studio 2019,
// this option is available on the Build page of the Project Properties window
// While assigning a null value to a non-nullable value type causes a compiler error,
// doing the same with a non-nullable reference type will only result in a warning (!)
// But we can still treat it as an error using the 'Treat warnings as errors' compiler option.
string nonNullable = null // warning at compile time
string? nullable = null;
string nonNullable = nullable; // warning at compile time
var length = nullable.Length; // warning at compile time
// static analysis is not perfect.
// Even if you get rid of all the warnings, there is still a possibility of a NullReferenceException being thrown at run time
var person = new Person("John", "Doe", "Unknown");
if (person.HomeCountry != null)
{
person.Relocate(); // sets HomeCountry to null
var countryLength = person.HomeCountry.Length; // no warning
}
// a new #nullable directive has been introduced into the language.
// use it to enable or disable the nullable reference types feature inside a single source code file.
// just put the following at the top fo the file:
#nullable disable // other options are 'enable' and 'restore'
// .net 5 annotated 94% of the netcoreapp assemblies for nullable reference types.
// In .NET 6.0/.NET 7.0, we plan to annotate the remaining 6% of that surface area
// and continue through other assemblies built from the dotnet/runtime repo.
//officially supported way to add annotations for nullable reference types to a .NET Standard 2.0 library
// manually add the following property to the project file to enable the use of C# 8:
<LangVersion>8.0</LangVersion>
// Json.net lib supports nullable reference types only from version 12
// even in version 12, code analysis won’t detect all potential NullReferenceExceptions thrown at run time
Player player = JsonConvert.DeserializeObject<Player>("null"); //assigns null to player
var username = player.Username; // no warning
// The only way to get a compile-time warning would be to modify the first line of code as follows:
var player = JsonConvert.DeserializeObject<Player?>("null");
var username = player.Username; // now we get warning
// notnull constraint can be useful in certain scenarios,
// but it doesn’t solve the initial problem of the missing warning.
// Even worse. It prevents the consuming code from using a nullable reference type
// as the generic type argument to get the compiler warning.
// But it does ensure that the type argument will always be nonnullable.
// we should add [return: MaybeNull] annotation attribute to get a compile time warning
[return: MaybeNull]
public static T DeserializeObject<T>(string json) where T: notnull
{
return JsonConvert.DeserializeObject<T>(json);
}
// MaybeNull attribute specifies that the return type value will be a nullable reference type
// even if the generic type argument is a non-nullable reference type
// a few more annotation atttributes are available:
// MaybeNull and NotNull have the exact opposite meaning
// Conditional variations for both are also available:
// MaybeNullWhen, NotNullWhen, and NotNullIfNotNull.
//for input values we have AllowNull and DisallowNull annotation attributes
// https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/nullable-analysis
// entity framework core docs
// https://docs.microsoft.com/en-us/ef/core/miscellaneous/nullable-reference-types
// To tell the compiler that the value is initialized without initializing it yourself,
// use the null-forgiving operator !
// null-forgiving operator tells the compiler to ignore that warning
public DbSet<Player> Players { get; set; } = null!;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment