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在这个条件下填写/:
我想找到所有
FirstBar的IsSelected==true.如果我找到了FirstBar哪一个IsSelected==false,那么我会SecondBar在FirstBar哪个下面查找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>'
我的推理是(显然是错误的),因为它们(FirstBar和SecondBar)都有相同的父(Foo),然后它们可以组合在它们的父(List<Foo>)的列表中.
顺便说一下,我知道如果我将它们分成不同的集合就可以解决,但最好有1个列表(因为在我的真实项目代码中,还有ThirdBar(这个集合在里面SecondBar)和FourthBar(这个集合在里面)的ThirdBar).
任何人都可以解释是什么造成的 我觉得我对这个问题的遗传基本失去了一些.
谢谢
问题无关这里的父母(和你不这样做呢联接) -它甚至不是在你的第二行.问题只是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>协方差.