首先,像奧利維爾上面說的,一個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
你的問題是什麼?你似乎已經有了一個解決方案。 –