我们如何使用yield返回空集合?

时间:2017-05-04 16:08:24

标签: c# linq ienumerable yield-return

我有以下扩展功能:

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

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);

我在这里遇到的问题是,即使serviceResponse.IsSuccessful为false,readFields也不为空,它包含一个带有null项的枚举。有没有办法可以在这里返回一个空集合?

3 个答案:

答案 0 :(得分:2)

这里真正的问题是,当服务没有成功响应时,您不想选择null值。您希望过滤掉成功的回复作为查询的一部分:

var readFields = from r in dsReader
    let serviceResponse = myService.Decrypt<DateTime>(r.GetString(DATE_VALUE), r.GetInt32(DEK_ID))
    where serviceResponse.IsSuccessful
    select new DataField<DateFieldValue>
    {
        FieldValue = new DateFieldValue { Data = serviceResponse.Value }
    };

答案 1 :(得分:1)

Select方法可以检查返回的结果,并且只在有效时才生成它的值。例如,不是null

public static IEnumerable<T> Select<T>(this IDataReader reader, Func<IDataReader, T> selector)
    where T:class
{   
    while (reader.Read())
    {   
        var res = selector(reader);
        if(res!=null)
            yield return res;
    }
}

虽然如Servy所述,这通常不属于常规Select。可以将此方法称为SelectValidValues,以避免混淆。

另一种方法是让lambda参数返回一个包含结果和它是否有效的元组。 另一种方法是使用可选参数(作为值或额外谓词函数)来检查哪些值有效

答案 2 :(得分:0)

有趣(错误?)使用Select。您的问题是,当SelectIsSuccessful时,您会从false代理返回空值。由于不能从Select委托中返回值,因此请在之后进行过滤:

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);