带接口和泛型的双向引用

时间:2011-11-02 15:14:01

标签: c# generics inheritance c#-4.0 interface

我有一个使用泛型的类,它使用另一个类,反过来需要知道初始类的哪个实例“拥有”它 - 这会导致问题;)让我举一个例子:

public interface IFoo<T>
{
}

public interface IBar
{
    IFoo<IBar> Foo { get; set; }
}

public class Foo<T> : IFoo<T> where T : IBar, new()
{
    private readonly T _bar;
    public Foo()
    {
        _bar = new T {Foo = this};
    }
}

class Bar : IBar
{
    public IFoo<IBar> Foo { get; set; }
}

这不起作用Foo =这不起作用 - 即使我尝试将其转换为IFoo(编译但在运行时失败)。我试图以各种方式调整代码,但我没有找到一个有效的实现......

希望你能看到我想要做的事情,也许你甚至可以看到我能做到这一点; - )

2 个答案:

答案 0 :(得分:4)

您可以使用构造函数中的显式强制转换以及c#4.0对泛型参数协方差的支持来解决此问题。

首先,您需要在Foo<T>构造函数中插入一个强制转换:

_bar = new T {Foo = (IFoo<IBar>)this};

但这样做还不够。 T : new()意味着T需要成为具体类的约束。因此,IFoo<T>永远不会完全IFoo<IBar>。但是,如果您指定T的通用参数IBar<T>是协变的,则从IFoo<Bar>IFoo<IBar>的强制转换将变为合法:

public interface IFoo<out T>

out关键字指定参数是协变的(这实际上意味着“此参数将仅由方法输出,从不输入。”)

This MSDN article提供了有关协方差和逆变的更多详细信息。

答案 1 :(得分:2)

T IFoo类型参数声明为协变可以解决您的问题吗?
此代码应该允许您执行您正在尝试的操作:

public interface IFoo<out T> {
}

public interface IBar {
    IFoo<IBar> Foo { get; set; }
}

public class Foo<T> : IFoo<T> where T : IBar, new() {
    private readonly T _bar;
    public Foo() {
        _bar = new T { Foo = (IFoo<IBar>)this };
    }
}

class Bar : IBar {
    public IFoo<IBar> Foo { get; set; }
}

public static class Program {

    public static void Main(params string[] args) {
        Bar b = new Bar();
        Foo<Bar> f = new Foo<Bar>();
    }

}
相关问题