简体   繁体   English

具有继承和接口的泛型-为什么这行不通?

[英]Generics with inheritance and interfaces - why doesn't this work?

Here's my entire application. 这是我的整个应用程序。 To me, this should compile fine. 对我来说,这应该可以编译。

namespace SampleApp
{
    interface I<T> where T : Image
    {
    }

    class A<T> where T : Image
    {
    }

    class B : A<Bitmap>, I<Bitmap>
    {
    }

    class C : A<Metafile>, I<Metafile>
    {
    }

    class Program
    {
        public static I<Image> SomeProperty { get; set; }

        static void Main(string[] args)
        {
            B b = new B();            
            SomeProperty = b;

            C c = new C();
            SomeProperty = c;
        }
    }
}

However, The lines "SomeProperty = b" and "SomeProperty = c" give the error: 但是,行“ SomeProperty = b”和“ SomeProperty = c”给出错误:

Cannot implicitly convert type 'B' to 'I<System.Drawing.Image>'. An explicit conversion exists (are you missing a cast?)

But I can't work out why. 但是我不知道为什么。 B implements I<Bitmap> , and Bitmap is a subclass of Image, so surely, by definition, B implements I<Image> . B实现I<Bitmap> ,而Bitmap是Image的子类,因此,根据定义,B当然可以实现I<Image>

As Sasha says, you're looking for generic covariance . 正如Sasha所说,您正在寻找泛型协方差 This may or may not be appropriate depending on what your interface members look like. 这可能合适也可能不合适,这取决于您的界面成员的外观。 If you only ever take values "out" of the interface, you can make your code compile by making T covariant: 如果只从接口中取出值,则可以通过使T成为协变量来使代码编译:

interface I<out T> where T : Image
{
}

However, if you have any methods accepting T , eg 但是,如果您有任何接受 T方法,例如

void ReplaceWith(T newImage)

then you can't make T covariant. 那么你就不能使T协变

Generic variance is a complicated topic - I gave a talk at NDC 2010 which you may find useful. 通用差异是一个复杂的话题-我在NDC 2010上发表了一个演讲,您可能会觉得有用。 You can watch it at the NDC video site . 您可以在NDC视频站点上观看它。 Search for "variance" to find it quickly. 搜索“方差”以快速找到它。 (The real content starts at about 2 minutes.) (实际内容大约在2分钟开始。)

No, it doesn't work that way with generics. 不,它不适用于泛型。 A may be a subclass of B, but G<A> is not a subclass of G<B> . A可能是B的子类,但G<A>不是G<B>的子类。 The same goes for interfaces. 接口也是如此。

You might be looking for a feature called generic covariance/contravariance, but to determine if you can use it in this case you would need to show us the real contents of the interface. 您可能正在寻找一种称为通用协方差/协方差的功能,但是要确定在这种情况下是否可以使用它,您需要向我们展示该接口的真实内容。

Change your interface to following to make it work: 将界面更改为以下内容以使其起作用:

interface I<out T> where T : Image
{
}

It is called Covariance . 这称为Covariance Read following link for more information: 阅读以下链接以获取更多信息:

Covariance and Contravariance FAQ 协方差和协方差常见问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM