Search code examples
c#nullablec#-8.0

How to avoid irrelevant nullable warning (without explicit suppression)


Is there a way to make the analyzer understand that the variable Bar has a value for the following case?

#nullable enable 
class Foo {
   bool GenerateArray => Bar.HasValue;
   int? Bar { get; set; }
   void FooBar() {
     var data = (GenerateArray) ? new int[Bar.Value] : null;
   }
}

There is the warning "Nullable value type may be null." for Bar.Value but it obviously can't be.

I am aware of two ways to avoid the warning. Both have disadvantages:

  1. Using Bar.HasValue directly instead of the property GenerateArray. However using GenerateArray improves readability.
  2. Using Bar!.Value instead of Bar.Value. However, if someone changes the code, for instance, by making GenerateArray an auto-property in the future, the warning may become relevant again, but won't appear.

The problem here slightly differs from this question, where a local variable was used instead of a property. The accepted answer below works (as soon as C# 9 is released) for the property but not for the local variable, if I understand it correctly. Hence, the question is not a duplicate.


Solution

  • Will be be able to use the MemberNotNullWhen attribute in C# 9 (currently in preview):

    [MemberNotNullWhen(true, "Bar")]
    bool GenerateArray => Bar.HasValue;
    

    The relevant attribute types will exist in .Net 5:

    namespace System.Diagnostics.CodeAnalysis
    {
        [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)]
        public sealed class MemberNotNullAttribute : Attribute
        {
            public MemberNotNullAttribute(params string[] members) { }
            public MemberNotNullAttribute(string member) { }
        }
    }
    
    namespace System.Diagnostics.CodeAnalysis
    {
        [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)]
        public sealed class MemberNotNullWhenAttribute : Attribute
        {
            public MemberNotNullWhenAttribute(bool when, params string[] members) { }
            public MemberNotNullWhenAttribute(bool when, string member) { }
        }
    }
    

    Illustration on sharplab