过滤IEnumerable

时间:2012-12-04 10:19:14

标签: c# filtering

我有3个具有以下属性的类:

OfferList类:

Guid Id
IEnumerable<Offer> Offers

提供课程:

Guid Id
Product Product
bool IsSealed

产品类别:

Guid Id

OfferList包含多个商品,商品包含1个商品。

如何过滤OfferList以仅包含未密封的商品?

OfferList offerList = this.GetOfferList(id).Offers.Where(o => !o.IsSealed));

这将返回一个类型为Offer的IEnumerable,而不是过滤OfferList。

4 个答案:

答案 0 :(得分:12)

有趣 - 你在这里提出的问题有点令人困惑。

你问的是如何Offers就地过滤。如果是这样的话:

IEnumerable<T>是不可变的(你必须强制转换为具体的List<T>或类似的才能获得可变性),OffersIEnumerable<T> - 所以你不能指望Offers.Where(o => !o.IsSealed)); 更改 Offers属性 - 它会返回一个可枚举的枚举,在您枚举时过滤源。

相反,你会做

var offerList = this.GetOfferList(id)
offerList.Offers = offerList.Offers.Where(o => !o.IsSealed));

但请注意,对于共享Offers实例的任何其他代码,这会隐藏原始OfferList引用。在你开始枚举之前,它也不会实际进行任何过滤。但这通常更可取。如果您希望在那里完成,那么 - 在.ToArray()的末尾使用.ToList()Where来强制完成枚举。

更好的方法是在OfferList类上拥有一个属性或方法,以便按需返回一个新的可枚举:

public IEnumerable<Offer> UnsealedOffers {
  get {
    return Offers.Where(o => !o.IsSealed);
  }
}

这样你就不会破坏可枚举的主人。

请注意,此代码容易Offers为空(NullReferenceException,返回null枚举并不好(返回空的枚举) - 所以如果Offers有可能为空 - 然后要么阻止它发生;或使用:

return (Offers ?? Enumerable.Empty<Offer>()).Where(o => !o.IsSealed);

答案 1 :(得分:1)

如果您要更新原始OfferList实例,则可以将过滤后的序列分配到其Offers字段:

OfferList offerList = this.GetOfferList(id);
offerList.Offers = offerList.Offers.Where(o => !o.IsSealed);

答案 2 :(得分:0)

您需要设置Offers课程的OfferList。您无法直接转换为OfferList,因为它不是List或未实现IEnumerable

OfferList list = new OfferList() { Offers = this.GetOfferList(id).Offers.Where(o => !o.IsSealed)) };

答案 3 :(得分:0)

您是否需要新的未密封优惠清单?

List<Offer> offers = this.GetOfferList(id).Offers
                         .Where(o => !o.IsSealed)
                         .ToList();