如何使用yield返回空集合?
问题描述:
我有以下扩展功能:如何使用yield返回空集合?
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假阅读字段不为空,它包含的问题具有null的项目的枚举。有没有办法可以在这里返回一个空集合?
答
有趣的(误?)使用的Select
。当IsSuccessful
为false
时,您的问题是您从Select
代表返回null。由于没有返回从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);
答
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参数返回一个包含结果和是否有效的Tuple。 另一种方法是有一个可选参数(作为一个值或一个额外的谓词函数)来检查哪些值是有效的
答
这里真正的问题是,你不想选择一个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 }
};
'Enumerable.Empty();' –
有没有一种方法)的reader.Read前检查(见如果有数据,并在进入之前返回null? – Neil
@Neil从预期的'IEnumerable'返回null几乎总是反模式。 –