HLQ002: Enumerable methods should not return null
May 13, 2020 ยท View on GitHub
Cause
A method that returns an enumerable type is returning null.
Severity
Error
Rule description
The following foreach loop:
foreach (var item in DoSomething())
Console.WriteLine(item);
is interpreted by the compiler as:
IEnumerator<int> enumerator = DoSomething().GetEnumerator();
try
{
while (enumerator.MoveNext())
{
int current = enumerator.Current;
Console.WriteLine(current);
}
}
finally
{
if (enumerator != null)
{
enumerator.Dispose();
}
}
If the method DoSomething() returns null, a NullReferenceException will be thrown when trying to call GetEnumerator().
The same issue applies to IAsyncEnumerator<T>.
null is not equivalent to an empty enumerable. An empty collection, is a collection where calls to its MoveNext() returns always false. While null is an invalid state.
How to fix violations
Return an instance of an empty collection.
When to suppress warnings
Should not be suppressed.
Example of a violation
IEnumerable<int> Method()
{
if (...)
return null;
...
}
IAsyncEnumerable<int> Method()
{
if (...)
return null;
...
}
Example of how to fix
Using an empty array:
using System;
IEnumerable<int> Method()
{
if (...)
return Array.Empty<int>();
...
}
Using an empty List<T>:
using System.Collections.Generic;
IEnumerable<int> Method()
{
if (...)
return new List<int>();
...
}
Using Enumerable.Empty<int>():
using System.Linq;
IEnumerable<int> Method()
{
if (...)
return Enumerable.Empty<int>();
...
}
Using AsyncEnumerable.Empty<int>() (requires System.Linq.Async package):
using System.Linq.Async;
IAsyncEnumerable<int> Method()
{
if (...)
return AsyncEnumerable.Empty<int>();
...
}