먼저,하는 List<Child>
는 Child
이 Parent
의 아이 인 경우에도 List<Parent>
의 서브 클래스가 아닙니다. ObservableCollection에서도 마찬가지입니다. 이 주제를 분산이라고합니다. 여기에 대해 깊이 논의하기에는 너무 멀어 지지만 자세한 내용은 C# : Is Variance (Covariance/Contravariance) another word for Polymorphism?을 참조하십시오. IEnumerable<T>
은 공변이다. 나는 그것으로 전환 할 것이다. 목록 또는 관찰 가능한 컬렉션이 특별히 필요하면 나중에 다르게 구성하거나 피드를 제공 할 수 있습니다.
ObservableCollection에서 임의의 IEnumerable을 반환하는 강력한 형식의 Get 함수가 있어야합니다. 여기서 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가 아닙니다. ObservableCollections
의 ObservableCollections
: 우리는 모든 것을 함께 넣어 경우, 우리는 여전히 당신이 원하는 행동을하지 않아도, 지금
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>)
}
를 얻을. 우리가 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");
}
}
, 그것은
내가 ManagerTemplate 항상 하나의 Obeservable를 개최 것을 올바르게 이해한다 "내가하는 A 해요"인쇄 부모의 단일 유형의 수집? – Martijn
네, 맞습니다. 각 ManagerTemplate 내부에는 동일한 유형의 객체를 포함하는 단일 ObserableCollection이 있습니다. – user2920222
그리고 당신의 질문은 무엇입니까? 당신은 이미 해결책이있는 것 같습니다. –