Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 244
MarkusParker Avatar asked Jul 01 '20 12:07

MarkusParker


People also ask

Which of the following feature's of nullable types help us avoid NullReferenceException?

NullReferenceException. Nullable reference types includes three features that help you avoid these exceptions, including the ability to explicitly mark a reference type as nullable: Improved static flow analysis that determines if a variable may be null before dereferencing it.

What is the point of nullable reference types?

Nullable reference types are a new feature in C# 8.0. They allow you to spot places where you're unintentionally dereferencing a null value (or not checking it.) You may have seen these types of checks being performed before C# 8.0 in ReSharper's Value and Nullability Analysis checks.

What is #nullable enable C#?

To enable per file, you can use #nullable enable where you want to enable the functionality and #nullable disable where you want to disable it. This means you can opt-in or opt-out of the nullable reference types where you want. This can be very useful to migrate an existing codebase.


Video Answer


1 Answers

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

like image 200
Julien Couvreur Avatar answered Nov 03 '22 00:11

Julien Couvreur