C# 嵌套泛型集合:如何实现从项到容器的引用?

C# 嵌套泛型集合:如何实现从项到容器的引用?,c#,generics,collections,nested,C#,Generics,Collections,Nested,在使用嵌套泛型集合实现设计时,我偶然发现了这些明显由C#的不变泛型引起的限制: Cannot convert from 'Collection<subtype of T> to 'Collection<T>' class Outer<TInner, TInnerItem> where TInner : Inner<TInnerItem> { public void Add(TInner item) { item.Ou

在使用嵌套泛型集合实现设计时,我偶然发现了这些明显由C#的不变泛型引起的限制:

Cannot convert from 'Collection<subtype of T> to 'Collection<T>'
class Outer<TInner, TInnerItem> where TInner : Inner<TInnerItem>
{
    public void Add(TInner item)
    {
        item.Outer = this; // ERROR:
            // Cannot implicitly convert from Outer<TInner, TInnerItem> 
            // to Outer<Inner<TInnerItem>, TInnerItem>
    }
}

class Inner<TInnerItem> : ICollection<TInnerItem>
{
    Outer<Inner<TInnerItem>, TInnerItem> _outer;

    public Outer<Inner<TInnerItem>, TInnerItem> Outer
    {
        set { _outer = value; }
    }
}
无法从“集合”转换为“集合” 这意味着,显然由于泛型的不变性,以下方法将不起作用:

Cannot convert from 'Collection<subtype of T> to 'Collection<T>'
class Outer<TInner, TInnerItem> where TInner : Inner<TInnerItem>
{
    public void Add(TInner item)
    {
        item.Outer = this; // ERROR:
            // Cannot implicitly convert from Outer<TInner, TInnerItem> 
            // to Outer<Inner<TInnerItem>, TInnerItem>
    }
}

class Inner<TInnerItem> : ICollection<TInnerItem>
{
    Outer<Inner<TInnerItem>, TInnerItem> _outer;

    public Outer<Inner<TInnerItem>, TInnerItem> Outer
    {
        set { _outer = value; }
    }
}
外层,其中镀锡层:内层
{
公共作废添加(TInner项)
{
item.Outer=this;//错误:
//无法从外部文件隐式转换
//外
}
}
类内部:ICollection
{
外(u Outer),;
公共外部
{
设置{u outer=value;}
}
}
(在实际代码中,
内部
外部
实现
i收集

我需要
内部
对象具有对其容器集合的引用,以便访问其某些数据

您将如何实现这些嵌套集合,最好使用上述通用方法?如何在
内部
类中设置对容器集合的引用

干杯

引入一个不依赖TInner的(可能是抽象的)基类可以帮助您:

abstract class OuterBase<TInnerItem>
{
}

class Outer<TInner, TInnerItem> : OuterBase<TInnerItem> where TInner : Inner<TInnerItem>
{
    public void Add(TInner item)
    {
        item.Outer = this; // Compiles
    }
}

class Inner<TInnerItem> : ICollection<TInnerItem>
{
    OuterBase<TInnerItem> _outer;

    public OuterBase<TInnerItem> Outer
    {
        set { _outer = value; }
    }
}
抽象类OuterBase
{
}
类别外部:外部基底,其中镀锡层:内部
{
公共作废添加(TInner项)
{
item.Outer=this;//编译
}
}
类内部:ICollection
{
外底(外底);;
公共外部基础外部
{
设置{u outer=value;}
}
}

或者等待C#4.0,它引入了co/contra-variant通用接口。

该语言不能让您从一个集合转换到另一个集合

让我解释一下原因

假设您有一个集合并将其转换为集合。没关系,因为subT继承自T

当您从
集合
中检索对象时,您可以确信它是正常的

稍后,将
T
对象添加到
T的集合中。现在,在subT的
集合中,有一个对象不是
subT
。哎呀

为了实现您想要的,您必须一起创建一个新集合

Collection<T> collection_of_T = new Collection<T>(collection_of_subT);
Collection-Collection-of-of-of-T=新集合(Collection-of-of-subT);

这可能对你不好。您真的需要
Outer
类中的
TInner
泛型参数吗?是否可以在代码的其余部分替换为
internal
。如果你给他们更清晰的名字,也许我可以试着理解你想做什么。谢谢你的回复。我想我明白为什么我不能在C#中进行这种类型的转换。在这里,我主要对如何解决引用问题的解决方案感兴趣:使内部泛型集合存储引用外部泛型集合。在我的代码中,这两个集合本身主要充当基类。然后,我将拥有Inner:DerivedInner:Inner的具体实现,并使用Outer作为in:Outer。对于我的具体问题,最后,我选择了这个解决方案。