我遇到了一个问题,我有一个泛型,我正在尝试转换为另一个,其中第二个通用T参数是第一个中使用的子类。
这是我的代码,为了理解而简化...
public partial class HierarchicalItem
{
public ObservableHierarchicalCollection<HierarchicalItem> ContainingCollection{ get; private set; }
public HierarchicalItem Parent{ get{
return (ContainingCollection != null)
? ContainingCollection.Owner
: null;
}}
}
public partial class HierarchicalItem
{
public class ObservableHierarchicalCollection<T> : ObservableCollection<T>
where T : HierarchicalItem
{
public ObservableHierarchicalCollection(HierarchicalItem owner)
{
this.Owner = owner;
}
public HierarchicalItem Owner{ get; private set; }
private void ExistingMemberCheck(T item)
{
if(item.ContainingCollection != null) throw new ExistingMemberException();
item.ContainingCollection = this; // <-- This fails because of casting
}
protected override void InsertItem(int index, T item)
{
ExistingMemberCheck(item);
base.InsertItem(index, item);
}
protected override void SetItem(int index, T item)
{
CheckParent(item);
// Get the item and unhook the hierarchy
var existingItem = this[index];
existingItem.ContainingCollection = null;
base.SetItem(index, item);
}
protected override void RemoveItem(int index)
{
// Get the item and unhook the hierarchy
var existingItem = this[index];
existingItem.ContainingCollection = null;
base.RemoveItem(index);
}
}
}
那么我该如何解决这个问题呢?
答案 0 :(得分:4)
C#4.0支持显式协方差和反方差。
您可以在 ObservableCollection 界面声明中使用 out 关键字:
public interface ObservableCollection <out T> {
//The ObservableCollection methods
}
然后界面将是共变体。
更多关于它:
Covariance and Contravariance (C# and Visual Basic)
Covariance and Contravariance FAQ
How is Generic Covariance & Contra-variance Implemented in C# 4.0?
答案 1 :(得分:0)
将顶部切换为类似的东西:
public partial class HierarchicalItem
{
public INotifyCollectionChanged ContainingCollection { get; private set; }
public HierarchicalItem Parent
{
get
{
return (ContainingCollection != null)
? ((ObservableHierarchicalCollection<HierarchicalItem>)ContainingCollection).Owner
: null;
}
}
}
你必须使用非通用接口,因为正如尼古拉斯所说,在这种情况下,共同方差是你的敌人。
答案 2 :(得分:0)
在您的示例中,ObservableHierarchicalCollection<T>
仅使用T = HierarchicalItem
进行实例化。如果情况总是这样,您可以尝试使该集合非通用,而是继承ObservableCollection<HierarchicalItem>
。
如果没有,您可以将HierarchicalItem
更改为抽象和通用,(HierarchicalItem<T> where T : HierarchicalItem<T>
),如IComparable和类似接口。然后,您将拥有DerivedItem : HierarchicalItem<DerivedItem>
,它将具有ObservableHierarchicalCollection类型的ContainingCollection。请注意,这可能会使混合项目类型变得困难。