不能在父母的同一集合下加入2个后代

时间:2014-09-24 06:01:27

标签: c# inheritance collections

这是我的班级结构:

public class MainWindow
{
    public List<FirstBar> FirstBars { get; set; }
    public List<Foo> SelectedFoos { get; set; }

    public MainWindow()
    {
        FirstBars = new List<FirstBar>();
        SelectedFoos = new List<Foo>();
    }
}

public abstract class Foo { public bool IsSelected { get; set; } }
public class FirstBar : Foo { public List<SecondBar> SecondBar { get; set; } }
public class SecondBar : Foo { }

...然后我想在这个条件下填写SelectedFoos

  

我想找到FirstBar的所有IsSelected==true。如果我   找到一个FirstBar IsSelected==false,然后我找每个   SecondBar FirstBar下的IsSelected==true {/ 1}}。

所以,根据这个条件,我在MainWindow的构造函数中进行集合初始化之后将它写到了某处:

/*assume below collections are already filled with some items.*/
SelectedFoos = FirstBars.Where(x => x.IsSelected).ToList(); //this is the error, below code is kinda irrelevant.
SelectedFoos.AddRange(FirstBars.Where(x => !x.IsSelected).SelectMany(x => x.SecondBars).Where(x => x.IsSelected).ToList();

但是,编辑说这是错误的/错误的:

  

无法隐式转换'...FirstBar>'类型转换为'...Foo>'

然后,我试过了:

/*assume below collections are already filled with some items.*/
SelectedFoos = (List<Foo>)FirstBars.Where(x => x.IsSelected).ToList(); //this is the error, below code is kinda irrelevant.
SelectedFoos.AddRange((List<Foo>)FirstBars.Where(x => !x.IsSelected).SelectMany(x => x.SecondBars).Where(x => x.IsSelected).ToList();

之后,错误变为:

  

无法转换键入'...FirstBar>''...Foo>'

我的推理是(显然是错误的),因为他们(FirstBarSecondBar)都有相同的父(Foo),然后他们可以组合在其父级列表中(List<Foo>)。

是的,我知道如果我把它们分成不同的集合就可以解决,但最好有1个列表(因为在我的真实项目代码中,还有ThirdBar(该集合位于SecondBar)和FourthBar内(此集合位于ThirdBar内)。

任何人都可以解释是什么造成的吗?我觉得我对这个问题的继承有点遗失。

谢谢

1 个答案:

答案 0 :(得分:5)

这个问题与这里的父母没有任何关系(而且你还没有进行加入) - 而且你的第二行甚至没有 。问题只是List<FirstBar>不是List<Foo>,即使每个FirstBar都是Foo。从.NET 4开始,使用通用协方差很容易解决这个问题:

SelectedFoos = FirstBars.Where(x => x.IsSelected).ToList<Foo>();

ToList上的显式类型参数意味着它基本上等同于:

IEnumerable<FirstBar> tmp = Enumerable.Where<FirstBar>(FirstBars, x => x.IsSelected);
SelectedFoos = Enumerable.ToList<Foo>(tmp);

使用IEnumerable<FirstBar>表达式可以转换为具有协方差的IEnumerable<Foo>这一事实。