MetalamaConceptual documentationUsing Metalama PatternsContractsValidating field, property and parameter valuesChecking all non-nullable references
Open sandboxFocusImprove this doc

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{
6    internal class Fabric : ProjectFabric
7    {
8        public override void AmendProject( IProjectAmender amender )
9        {
10            amender.Outbound.VerifyNotNullableDeclarations();
11        }
12    }
13}
Source Code
1using Metalama.Patterns.Contracts;
2

3namespace Doc.NotNullFabric
4{
5    public 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
18    public 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    }
28}
Transformed Code
1using System;
2using Metalama.Patterns.Contracts;
3
4namespace Doc.NotNullFabric
5{
6    public class Instrument
7    {
8        private string _name = default!;
9
10        public string Name
11        {
12            get
13            {
14                return this._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                this._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
42    public 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    }
52}