在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 where T : HierarchicalItem ),如IComparable和类似接口所做的那样。 然后,您将拥有DerivedItem : HierarchicalItem ,它将具有ObservableHierarchicalCollection类型的ContainingCollection。 请注意,这可能会使混合项类型变得困难。