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.
}
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 ifA
evaluates tonull
andC
isn't evaluated ifA
orB
evaluates tonull
: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();