首先,像奥利维尔上面说的,一个List<Child>
不是List<Parent>
一个子类,即使Child
是Parent
一个孩子。 ObservableCollection也是一样。这个主题被称为方差。在这里深入讨论它太远了,但你可以看看C# : Is Variance (Covariance/Contravariance) another word for Polymorphism?了解更多细节。 IEnumerable<T>
是协变的。我将转向那个。如果你特别需要列表或可观察的集合,你可以简单地构造它们,或者甚至喂它们。
你想要的是一个强类型的Get函数,它从ObservableCollection> U中返回任意的IEnumerable,其中U是T的孩子让我们看看,如果我们可以写一个签名:
IEnumerable<U> Get<U, T>(ObservableCollection<IEnumerable<T>> source) where U : T
这就是我们想要的最抽象的版本,但我们实际上并不需要它是通用的:我们已经知道编译时的基类型。为了方便阅读,我们可以让它更加具体:
IEnumerable<U> Get<U>(ObservableCollection<IEnumerable<Parent>> source) where U : Parent
现在,让我们认真填写函数体:
IEnumerable<U> Get<U>(ObservableCollection<IEnumerable<Parent>> source) where U : Parent {
return source.First(inner => inner is IEnumerable<U>)
}
哇,这是其实很简单!
这不是你想要的api。如果我们把一切融合在一起,我们得到
ObservableCollection<IEnumerable<Parent>> ManagerListStack = new ObservableCollection<IEnumerable<Parent>>(ManagerTemplates);
internal static List<IEnumerable<Parent>> ManagerTemplates = new List<IEnumerable<Parent>>
{
new IEnumerable<ChildA>(){},
new IEnumerable<ChildB>(){},
};
IEnumerable<U> Get<U>() where U : Parent {
return ManagerListStack.First(inner => inner is IEnumerable<U>)
}
现在为止,我们还没有你想要的行为:的ObservableCollections
ObservableCollections
。事实证明,我们无法在C#的类型系统中正确执行此操作。然而,我们可以做的是将责任从类型系统转移到程序员。我们保留ObservableCollection<IEnumerable<Parent>>
,但我们填写ObservableCollections<Child>
。这是可能的,因为ObservableCollection<Child>
实体IEnumerable<Child>
和IEnumerable<Child>
是IEnumerable<Parent>
的子类型。
ObservableCollection<IEnumerable<Parent>> ManagerListStack = new ObservableCollection<IEnumerable<Parent>>(ManagerTemplates);
internal static List<IEnumerable<Parent>> ManagerTemplates = new List<IEnumerable<Parent>>
{
new ObservableCollection<ChildA>(){},
new ObservableCollection<ChildB>(){},
};
ObservableCollection<U> Get<U>() where U : Parent {
return (ObservableCollection<U>)ManagerListStack.First(inner => inner is ObservableCollection<U>)
}
我们使用铸铁作为逃生舱口要解决这个问题并没有提供一个共同的变体的ObservableCollection库的限制(这似乎是不可能的,无论如何,所以不要责怪他们吧)
完整的程序我在LinqPad用于测试:
void Main()
{
new Test().Get<ChildA>().First().Talk();
}
class Test {
internal List<IEnumerable<Parent>> ManagerTemplates;
private ObservableCollection<IEnumerable<Parent>> ManagerListStack;
public Test() {
this.ManagerTemplates = new List<IEnumerable<Parent>>
{
new ObservableCollection<ChildA>(){ new ChildA()},
new ObservableCollection<ChildB>(){ new ChildB()},
};
this.ManagerListStack = new ObservableCollection<IEnumerable<Parent>>(this.ManagerTemplates);
}
public ObservableCollection<U> Get<U>() where U : Parent {
return (ObservableCollection<U>)ManagerListStack.FirstOrDefault(inner => inner is ObservableCollection<U>);
}
}
abstract class Parent {
abstract public void Talk();
}
class ChildA : Parent {
public override void Talk(){
Console.WriteLine("I'm an A");
}
}
class ChildB : Parent {
public override void Talk(){
Console.WriteLine("I'm a B");
}
}
正如预期的那样,它打印“我是一个A”
我理解正确的话那ManagerTemplate将始终保持一个Obeservable单一类型的父类的集合? – Martijn
是的,正确的。每个ManagerTemplate内部都将是一个包含相同类型对象的ObserableCollection。 – user2920222
你的问题是什么?你似乎已经有了一个解决方案。 –