Search code examples
c#linqienumerableyield-return

How can we return an empty collection using yield?


I have following extension function:

public static IEnumerable<T> Select<T>(this IDataReader reader,
                               Func<IDataReader, T> selector)
{
    while (reader.Read())
    {
        yield return selector(reader);
    }
}

which is being used like:

var readFields = dsReader.Select(r =>
{
    var serviceResponse = myService.Decrypt<DateTime>(r.GetString(DATE_VALUE), r.GetInt32(DEK_ID));

    if (serviceResponse.IsSuccessful)
    {
        return new DataField<DateFieldValue>
        {
            FieldValue = new DateFieldValue { Data = serviceResponse.Value }
        };
    }
    return null;
});

if (!readFields.IsCollectionNullOrEmpty())
                        returnFinalFields.AddRange(readFields);

The problem I am facing here is that even if serviceResponse.IsSuccessful is false the readFields is not empty it contains an enumerable with an item that is null. Is there a way we can return an empty collection here?


Solution

  • Interesting (mis?) use of Select. Your issue is you return a null from the Select delegate when IsSuccessful is false. Since not returning a value from Select's delegate isn't an option, filter afterwards:

    var readFields = dsReader.Select(r => {
        var serviceResponse = myService.Decrypt<DateTime>(r.GetString(DATE_VALUE), r.GetInt32(DEK_ID));
    
        if (serviceResponse.IsSuccessful)
            return new DataField<DateFieldValue> {
                FieldValue = new DateFieldValue { Data = serviceResponse.Value }
            };
        else
            return null;
    }).Where(df => df != null);