【问题标题】:Two way reference with interfaces and generics接口和泛型的两种方式引用
【发布时间】:2011-11-02 15:14:00
【问题描述】:

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

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(编译但在运行时失败)。我尝试以各种方式调整代码,但我没有找到可行的实现......

希望您能看到我正在尝试做的事情,也许您甚至会看到我如何实现这一目标 ;-)

【问题讨论】:

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


    【解决方案1】:

    您可以结合构造函数中的显式转换以及 c#4.0 对泛型参数协变的支持来解决此问题。

    首先,您需要在Foo&lt;T&gt; 构造函数中插入一个强制转换:

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

    不过,仅仅这样做是不够的。您对 T : new() 的约束意味着 T 需要是一个具体的类。因此,IFoo&lt;T&gt; 永远不会完全是 IFoo&lt;IBar&gt;。但是,如果您指定IBar&lt;T&gt; 的泛型参数T 是协变的,那么从IFoo&lt;Bar&gt;IFoo&lt;IBar&gt; 的转换将变得合法:

    public interface IFoo<out T>
    

    out关键字指定参数是协变的(本质上意味着“这个参数只会被方法输出,绝不会输入。”)

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

    【讨论】:

    • 成功了!解决了一个问题并学到了一些新东西。不错:) 谢谢!
    【解决方案2】:

    IFooT 类型参数声明为协变可以解决您的问题吗?
    这段代码应该允许你做你正在尝试的事情:

    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>();
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-06
      • 1970-01-01
      • 2018-01-01
      • 2011-03-14
      • 1970-01-01
      • 2012-03-01
      相关资源
      最近更新 更多