Yield Return Over Child Objects
-
26-05-2021 - |
Question
I have a list of items ('sections') which has a getter and a setter. Each one of these 'sections' has a list of 'items'. I'd like to provide a yield return property to expose an 'Items' property as an IEnumerable on the containing class. I just can't get the syntax quite right. Do I need another loop in here or will that iterate too many times?
public virtual IList<ISection> Sections{ get; set; }
public virtual IEnumerable<IItem> Sections {
get{
foreach (var sect in Sections) {
// will this iterate too many times if I add an additional loop?
yield return sect.Items
}
}
}
Solution
You could also use SelectMany
public virtual IEnumerable<IItem> Sections
{
get { return Sections.SelectMany(s => s.Items); }
}
OTHER TIPS
You are correct; the extra loop should do what you want - although you won't then know from the calling code which section the item belonged to. So if that's a requirement you may want to rethink your code.
public virtual IEnumerable<IItem> Sections {
get{
foreach (var sect in Sections) {
foreach (var item in sect.Items) {
yield return item;
}
}
}
As mentioned, you can't have two properties with the same name that return different types. You need to rename one of the methods.
Also, you can make the property a one-liner with Linq:
public virtual IList<ISection> Sections { get; set; }
public virtual IEnumerable<IItem> SectionItems
{
get {
return Sections.SelectMany(sect => sect.Items);
}
}