c# - 方法 C# 的通用抽象参数

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

最佳答案

此问题已在此站点上被问过数百次。

假设您有一碗水果。是一碗苹果吗?一个苹果是一种水果,那为什么一碗水果不是一碗苹果呢?显然,因为一碗水果可能已经包含香蕉,而一碗苹果则不是。

假设您有一碗苹果。是一碗水果吗?你想说“一个苹果是一种水果,因此一碗苹果就是一碗水果”。但这是错误的。 一碗水果是你可以放一根香蕉的东西,因为有一个你可以在一碗水果上做的操作你不能在一碗苹果上做,所以一碗苹果不能用于预期有一碗水果的语境。

您想要的那种转换的技术名称是“通用协变转换”。 C# 仅在少数特定情况下支持通用协变转换:

  • “外部”类型必须是接口(interface)或委托(delegate),例如 IEnumerable<T> .
  • “内部”类型必须是引用类型,如字符串,而不是值类型,如 int。
  • “外部”类型必须标记为协变安全;这是由编译器检查的。

您可以使用 IEnumerable<Apple>IEnumerable<Fruit> 的上下文中这是意料之中的,因为没有办法将香蕉放入 IEnumerable<Fruit>。但是你不能使用你的类 A<Apple>作为A<Fruit>因为编译器不相信您已经阻止了在只能接受 Apple 的方法中使用扩展 Fruit 的另一种 Banana 类型的所有可能性。

在此站点上搜索“协变和逆变”,您会发现很多关于此的问题。

关于c# - 方法 C# 的通用抽象参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45784081/

相关文章:

c# - Fiddler 和 .Net 3.5 SSL 错误。在 .Net 4.0 中工作正常

java - 找到重叠部分的最大数量

c# - 如何创建一次性类

c# - net5 自包含 exe 缺少一些系统 DLL

c# - 为每个数据透视项标题分配一个图像

.net - 编辑 WCF 服务自动生成的 DMBL 文件

c# - 学习 C#、ASP.NET 3.5 - 我应该按照什么顺序学习/跳过什么?

c# - C#中 "Network path not found"和 "Access denied"的区别

c# - 来自托管线程 ID 的 Windows 线程 ID

c# - 如何通过textbox和datagridview更新主键