接口和泛型的两种方式引用

发布于 2024-12-13 10:29:12 字数 556 浏览 0 评论 0原文

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

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 = this不起作用 - 即使我尝试将其转换为 IFoo (编译但在运行时失败)。我尝试以各种方式调整代码,但我还没有找到有效的实现...

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

I've got a class with generics which uses another class, which in return needs to know what instance of the initial class "owns" it - which causes problems ;) Let me give an example:

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

This doesn't work as Foo = this doesn't work - even if I try to cast this to IFoo (compiles but fails at run time). I've tried to tweak the code various ways, but I've not found an implementation that works...

Hopefully you see what I'm trying to do, and perhaps you even see how I can achieve this ;-)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

庆幸我还是我 2024-12-20 10:29:12

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

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

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

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

public interface IFoo<out T>

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

这篇 MSDN 文章 提供了有关协变和逆变的更多详细信息。

You can solve this with a combination of an explicit cast in the constructor, along with c#4.0 support for covariance on generic parameters.

First, you need to insert a cast in the Foo<T> constructor:

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

Just doing that isn't sufficient, though. Your constraint that T : new() means that T needs to be a concrete class. As such, IFoo<T> will never be exactly IFoo<IBar>. However, if you specify that the generic parameter T for IBar<T> is covariant, then the cast from IFoo<Bar> to IFoo<IBar> will become legal:

public interface IFoo<out T>

The out keyword specifies that the parameter is covariant (which essentially means "this parameter will only be output by methods, never input.")

This MSDN article offers more details on covariance and contravariance.

北城半夏 2024-12-20 10:29:12

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

}

Would declaring the T type parameter of IFoo as covariant solve your problem?
This code should allow you to do what you are trying:

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

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文