具有继承和接口的泛型 - 为什么这不起作用?

时间:2011-02-09 10:56:45

标签: c# .net interface generics

这是我的整个申请。对我来说,这应该编译得很好。

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

但是,“SomeProperty = b”和“SomeProperty = c”这一行会出错:

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

但我无法理解为什么。 B实现了I<Bitmap>,而Bitmap是Image的子类,所以根据定义,B实现了I<Image>

3 个答案:

答案 0 :(得分:3)

正如Sasha所说,你正在寻找通用协方差。根据您的界面成员的外观,这可能适合也可能不适合。如果您只是从界面中取出值,则可以通过使T协变来编译代码:

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

但是,如果您有任何方法接受 T,例如

void ReplaceWith(T newImage)

然后你无法使T协变。

通用差异是一个复杂的话题 - 我在NDC 2010上发表了一篇你认为有用的演讲。您可以在NDC video site处观看。搜索“差异”以快速找到它。 (实际内容大约2分钟开始。)

答案 1 :(得分:2)

不,它与泛型不一样。 A可以是B的子类,但G<A>不是G<B>的子类。接口也是如此。

您可能正在寻找一种称为通用协方差/逆变的功能,但为了确定您是否可以在这种情况下使用它,您需要向我们展示界面的真实内容。

答案 2 :(得分:1)

将您的界面更改为以下内容以使其正常工作:

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

它被称为Covariance。请阅读以下链接以获取更多信息:

Covariance and Contravariance FAQ