如何使用yield返回空集合?

如何使用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的项目的枚举。有没有办法可以在这里返回一个空集合?

+3

'Enumerable.Empty ();' –

+0

有没有一种方法)的reader.Read前检查(见如果有数据,并在进入之前返回null? – Neil

+2

@Neil从预期的'IEnumerable '返回null几乎总是反模式。 –

有趣的(误?)使用的Select。当IsSuccessfulfalse时,您的问题是您从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。 另一种方法是有一个可选参数(作为一个值或一个额外的谓词函数)来检查哪些值是有效的

+1

然后它不再选择。这不属于“选择”方法。 – Servy

+1

@Servy确实,但也许OP有不同的想法如何'选择'应该表现?重命名为'SelectNotEmpty'对于公共代码来说可以。 –

+0

@AlexeiLevenkov这只是创建一个新问题。 LINQ没有'SelectNotEmpty'方法是有原因的。如果要投影,则使用投影方法,如果要过滤,则使用滤镜方法。你不要将它们组合成一个可以做两件不相关事情的单一方法。此外,在这里依然使用'null'作为表示失败响应的语义错误。 *那*是需要解决的问题。 – Servy

这里真正的问题是,你不想选择一个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 } 
    }; 
+0

或者在lambda语法中'var readFields = dsReader.Select(r => myService.Decrypt其中(sr => sr.IsSuccessful).Select(new DataField {FieldValue = new DateFieldValue {Data = serviceResponse.Value}}); ' – NetMage

+0

顺便说一句,非常好的问题反转,使其更优雅。 – NetMage