方法C#的通用抽象参数

时间:2017-08-20 15:57:44

标签: c# .net

我有这个代码示例。我不知道它为什么不编译。它不允许从D转换为A<B>

D继承A<C>C继承了B,这意味着我应该能够将D传递给A<B>方法论证吗?我可能在这里遗漏了一些明显的东西。

using System.Collections.Generic;

public class Program
{
    public void Main()
    {
        var d = new D();
        Foo(d);  //Cannot convert D to A<B>

    }

    private void Foo(A<B> bar)
    {

    }   
}

public abstract class A<TypeB> where TypeB : B
{
     public abstract List<TypeB> list { get; set; } 
}

public abstract class B
{
}

public class C : B
{

}

public class D : A<C>
{
     public override List<C> list { get; set; }
}

1 个答案:

答案 0 :(得分:9)

这个问题已在本网站上被问过数百次。

假设你有一碗水果。是一碗苹果吗?苹果是一种水果,为什么一碗水果不是一碗苹果?显然是因为一碗水果已经含有香蕉,所以不是一碗苹果。

假设你有一碗苹果。这是一碗水果吗?你想说'苹果是一种水果,因此一碗苹果就是一碗水果&#34;。但这是错误的。 一碗水果是你可以放入香蕉的东西,因为有一个手术你可以在一碗水果上进行,你不能在一碗苹果上做,一碗苹果不能用于预期一碗水果的环境中。

您想要的转换类型的技术名称是&#34;泛型协变转换&#34;。 C#仅在少数特定情况下支持通用协变转换:

  • &#34;外部&#34; type必须是接口或委托,例如IEnumerable<T>
  • &#34;内部&#34; type必须是引用类型,如字符串,而不是值类型,如int。
  • &#34;外部&#34;类型必须标记为协方差安全;这由编译器检查。

您可以在期望IEnumerable<Apple>的上下文中使用IEnumerable<Fruit>,因为无法将香蕉放入IEnumerable<Fruit> 。但是你不能将你的A<Apple>类用作A<Fruit>,因为编译器不相信你已经阻止了另一种类型Banana的可能性,它扩展了Fruit只能接受一个只能接受Apple的方法。 / p>

在本网站上搜索&#34;协方差和逆变&#34;你会发现很多关于此的问题。