Search code examples
c#nullable-reference-types

Nullable reference type not working without an intermediate variable


I have this code and I don't understand why the last line gives me a warning if the previous two don't:

    [return: NotNull]
    public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T>? sourceEnumerable) => sourceEnumerable ?? Array.Empty<T>();

    public static void ConfigurationSectionTest(IConfigurationSection? cfg)
    {
        IEnumerable<IConfigurationSection>? myChildren = cfg?.GetChildren();
        IEnumerable<IConfigurationSection> safeChildren = myChildren.EmptyIfNull();
        IEnumerable<IConfigurationSection> safeChildren2 = cfg?.GetChildren().EmptyIfNull(); //Warning: Converting null literal or possible null value to non-nullable type.
    }

Solution

  • Check out the docs for the Null-conditional operators ?. and ?[] :

    The null-conditional operators are short-circuiting. That is, if one operation in a chain of conditional member or element access operations returns null, the rest of the chain doesn't execute. In the following example, B isn't evaluated if A evaluates to null and C isn't evaluated if A or B evaluates to null:

    A?.B?.Do(C);
    A?.B?[C];
    

    Hence the cfg?.GetChildren().EmptyIfNull(); is null if cfg is null.

    One workaround is to use parenthesis:

    // no warning
    IEnumerable<IConfigurationSection> safeChildren2 = (cfg?.GetChildren()).EmptyIfNull();