Checking all non-nullable fields, properties and parameters
If you're already using the nullability feature introduced in C# 8.0, you're aware that C# only reports a warning when there's an attempt to assign a null value to a non-nullable field, property, or parameter. C# does not generate the code that would throw an exception at runtime if this happens. However, if your API is being consumed by code that isn't under your control, it's still a good idea to check all values for null.
If you find this task repetitive, frustrating, and unworthy of clean code, we share your sentiment.
Rejoice, solving this problem is a one-liner with Metalama! Simply call the VerifyNotNullableDeclarations method from your ProjectFabric.
Note
By default, only your public API is verified. To add checks to your internal API, set the includeInternalApis
parameter to true
.
Example: enforcing all non-nullable fields, properties and parameters
In the following example, we use the VerifyNotNullableDeclarations method to inject null-checks for our complete public API. Yes, in just one line.
1using Metalama.Framework.Fabrics;
2using Metalama.Patterns.Contracts;
3
4namespace Doc.NotNullFabric;
5
6internal class Fabric : ProjectFabric
7{
8 public override void AmendProject( IProjectAmender amender )
9 {
10 amender.VerifyNotNullableDeclarations();
11 }
12}
1using Metalama.Patterns.Contracts;
2
3namespace Doc.NotNullFabric;
4
5public class Instrument
6{
7 public string Name { get; set; }
8
9 public Category? Category { get; set; }
10
11 public Instrument( string name, Category? category )
12 {
13 this.Name = name;
14 this.Category = category;
15 }
16}
17
18public class Category
19{
20 // Internal APIs won't be checked by default.
21 internal Category( string name )
22 {
23 this.Name = name;
24 }
25
26 public string Name { get; }
27}
1using System;
2using Metalama.Patterns.Contracts;
3
4namespace Doc.NotNullFabric;
5
6public class Instrument
7{
8 private string _name = default!;
9
10 public string Name
11 {
12 get
13 {
14 return _name;
15 }
16
17 set
18 {
19 if (value == null!)
20 {
21 throw new ArgumentNullException("value", "The 'Name' property must not be null.");
22 }
23
24 _name = value;
25 }
26 }
27
28 public Category? Category { get; set; }
29
30 public Instrument(string name, Category? category)
31 {
32 if (name == null!)
33 {
34 throw new ArgumentNullException("name", "The 'name' parameter must not be null.");
35 }
36
37 this.Name = name;
38 this.Category = category;
39 }
40}
41
42public class Category
43{
44 // Internal APIs won't be checked by default.
45 internal Category(string name)
46 {
47 this.Name = name;
48 }
49
50 public string Name { get; }
51}