【问题标题】:Generics with inheritance and interfaces - why doesn't this work?具有继承和接口的泛型 - 为什么这不起作用?
【发布时间】:2011-02-09 10:56:44
【问题描述】:

这是我的整个应用程序。对我来说,这应该编译得很好。

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&lt;Bitmap&gt;,而Bitmap 是Image 的子类,所以根据定义,B 肯定实现了I&lt;Image&gt;

【问题讨论】:

  • 您使用的是哪个版本的 .NET Framework?
  • .NET 4,很抱歉漏掉了。

标签: c# .net interface generics


【解决方案1】:

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

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

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

void ReplaceWith(T newImage)

那么你不能使T协变。

泛型方差是一个复杂的话题 - 我在 NDC 2010 上发表了一个演讲,您可能会发现它很有用。您可以在NDC video site 观看。搜索“方差”以快速找到它。 (真正的内容从大约 2 分钟开始。)

【讨论】:

  • 谢谢。我将把逻辑应用到我的“真实世界”应用程序中,看看我是怎么做的。
【解决方案2】:

不,它不适用于泛型。 A 可能是 B 的子类,但 G&lt;A&gt; 不是 G&lt;B&gt; 的子类。接口也是如此。

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

【讨论】:

  • 谢谢,显然G&lt;A&gt; is not a subclass of G&lt;B&gt; 是我的错误假设。我会阅读协方差,如果我不能让它适用于我的情况,我会问一个新问题。
【解决方案3】:

将您的界面更改为以下以使其工作:

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

它被称为Covariance。阅读以下链接了解更多信息:

Covariance and Contravariance FAQ

【讨论】:

  • 谢谢,现在我知道我要查找的内容的名称了。
猜你喜欢
  • 2021-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-04
  • 2016-03-22
  • 1970-01-01
相关资源
最近更新 更多