Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make C# aware of the nullability of convenient properties?

Consider this code snippet, which has no nullable warnings.

public class Foo {
    public string Property { get; } = "Some String";
}

public class Bar {
    [DisallowNull]
    public Foo? Foo { get; private set; }
    
    [MemberNotNull(nameof(Foo))]
    public void MyMethod() {
        Foo = new Foo();
        
        // After setting Foo, I use Foo.Property in some way
        Console.WriteLine(Foo.Property);
    }
}

Since in my real code, I use Foo.Property after setting Foo a lot, I wanted to add a "convenient property" to Bar that returns it directly, so that I can access it with a shorter name (Foo is actually a rather long name in my real code):

// in Bar
public string? Property => Foo?.Property;

// ...
// Now I can do:
Console.WriteLine(Property);

However, now Bar.Property is nullable, even in a place where Foo is definitely not null (such as just after setting Foo). So when I use Property in a place where null is not allowed, the compiler gives me warnings.

I thought what I needed is to annotate Property with something like NotNullIfMemberNotNull(nameof(Foo)), but after looking it up, this attribute is only proposed, and doesn't exist yet.

How can I work around this?

like image 891
Sweeper Avatar asked Sep 02 '25 16:09

Sweeper


1 Answers

One workaround I came up with is make both Foo and Property have backing fields. In the setter of Foo, also set Property. This way, we can add the MemberNotNull attribute to the setter of Foo.

private Foo? foo;

[DisallowNull]
public Foo? Foo { 
    get => foo;
    [MemberNotNull(nameof(Property))]
    private set {
        foo = value;
        Property = value.Property;
    }
}

public string? Property { get; private set; }

However, this isn't very general. It only works because Foo just happens to be marked as DisallowNull.

like image 127
Sweeper Avatar answered Sep 05 '25 05:09

Sweeper