在C#中,你可以将一个generics类型转换为另一个T参数是第一个T的子类吗?
我遇到了一个问题,我有一个generics,我正试图转换到另一个,其中第二个的genericsT参数是第一个中使用的子类。
这是我的代码,为了理解而简化…
public partial class HierarchicalItem { public ObservableHierarchicalCollection ContainingCollection{ get; private set; } public HierarchicalItem Parent{ get{ return (ContainingCollection != null) ? ContainingCollection.Owner : null; }} } public partial class HierarchicalItem { public class ObservableHierarchicalCollection : ObservableCollection 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); } } }
那么我该如何解决这个问题呢?
C#4.0支持显式协方差和反方差。
您可以在ObservableCollection接口声明中使用out关键字:
public interface ObservableCollection { //The ObservableCollection methods }
然后界面将是共变体。
更多关于它:
协方差和逆变(C#和Visual Basic)
协方差和逆变法常见问题解答
如何在C#4.0中实现通用协方差和反差异?
将顶部切换为如下所示:
public partial class HierarchicalItem { public INotifyCollectionChanged ContainingCollection { get; private set; } public HierarchicalItem Parent { get { return (ContainingCollection != null) ? ((ObservableHierarchicalCollection)ContainingCollection).Owner : null; } } }
你必须使用非通用接口,因为正如尼古拉斯所说,在这种情况下,共同方差是你的敌人。
在您的示例中, ObservableHierarchicalCollection
仅使用T = HierarchicalItem
实例化。 如果情况总是这样,您可以尝试使集合非generics,而是inheritance自ObservableCollection
。
如果没有,您可以将HierarchicalItem
更改为抽象和通用( HierarchicalItem
),如IComparable和类似接口所做的那样。 然后,您将拥有DerivedItem : HierarchicalItem
,它将具有ObservableHierarchicalCollection类型的ContainingCollection。 请注意,这可能会使混合项类型变得困难。