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

Mos*_*ico 1 c# collections inheritance

这是我的班级结构:

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 { }
Run Code Online (Sandbox Code Playgroud)

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

我想找到所有FirstBarIsSelected==true.如果我找到了FirstBar哪一个IsSelected==false,那么我会SecondBarFirstBar哪个下面查找 IsSelected==true.

所以,根据这个条件,我在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();
Run Code Online (Sandbox Code Playgroud)

但是,编辑说它错了/错误:

不能隐式转换类型'...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();
Run Code Online (Sandbox Code Playgroud)

之后,错误更改为:

无法类型转换'...FirstBar>''...Foo>'

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

顺便说一下,我知道如果我将它们分成不同的集合就可以解决,但最好有1个列表(因为在我的真实项目代码中,还有ThirdBar(这个集合在里面SecondBar)和FourthBar(这个集合在里面)的ThirdBar).

任何人都可以解释是什么造成的 我觉得我对这个问题的遗传基本失去了一些.

谢谢

Jon*_*eet 5

问题无关这里的父母(和你不这样做呢联接) -它甚至不是你的第二行.问题只是a List<FirstBar>不是a List<Foo>,即使每个FirstBar都是a Foo.从.NET 4开始,使用通用协方差很容易解决这个问题:

SelectedFoos = FirstBars.Where(x => x.IsSelected).ToList<Foo>();
Run Code Online (Sandbox Code Playgroud)

显式类型参数on ToList表示这基本等同于:

IEnumerable<FirstBar> tmp = Enumerable.Where<FirstBar>(FirstBars, x => x.IsSelected);
SelectedFoos = Enumerable.ToList<Foo>(tmp);
Run Code Online (Sandbox Code Playgroud)

这是因为IEnumerable<FirstBar>表达式可以转换为IEnumerable<Foo>协方差.