过滤IEnumerable

nik*_*klr 7 c# filtering

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

OfferList类:

Guid Id
IEnumerable<Offer> Offers
Run Code Online (Sandbox Code Playgroud)

优惠等级:

Guid Id
Product Product
bool IsSealed
Run Code Online (Sandbox Code Playgroud)

产品类别:

Guid Id
Run Code Online (Sandbox Code Playgroud)

OfferList包含多个Offer,而Offer具有精确的1个产品.

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

OfferList offerList = this.GetOfferList(id).Offers.Where(o => !o.IsSealed));
Run Code Online (Sandbox Code Playgroud)

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

And*_*tan 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));
Run Code Online (Sandbox Code Playgroud)

但请注意,这会隐藏Offers共享该OfferList实例的任何其他代码的原始引用.在你开始枚举之前,它也不会实际进行任何过滤.但这通常更可取.如果你想在那里完成它然后 - 使用.ToArray().ToList()在结束时Where强制完成枚举.

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

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

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

请注意,此代码很容易为Offersnull(a NullReferenceException),并且返回null枚举并不是很好(而是返回空的枚举) - 所以如果有机会Offers可以为null - 那么要么阻止它发生; 或使用:

return (Offers ?? Enumerable.Empty<Offer>()).Where(o => !o.IsSealed);
Run Code Online (Sandbox Code Playgroud)