在 C# 中,协变和逆变能够实现数组类型、委托类型和泛型类型参数的隐式引用转换。 协变保留分配兼容性,逆变则与之相反。
msdn 解释如下:
“协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型。
“逆变”则是指能够使用派生程度更小的类型。
“协变”->”和谐的变”->”很自然的变化”->string->object :协变。
“逆变”->”逆常的变”->”不正常的变化”->object->string 逆变。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public abstract class Animal
{
}
public class Dog : Animal
{
}
namespace xbdemo
{
class Program
{
public static void Main(string[] args)
{
Dog gougou1 = new Dog();
Animal anm1 = gougou1;
List<Dog> lstdogs = new List<Dog>();
//List<Animal> lstanm = lstdogs;
//List<Animal> lstanm2 = lstdogs.Select(d => (Animal)d).ToList();
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
}
代码中有2句注释的,先把第二句注释掉,保留第一句,构建;
因为Dog继承自Animal,所以Animal anm1 = gougou1; gougou1 会隐式的转变为Animal;
但是List<Dog> 不继承List<Animal> 所以出现错误提示 CS0029,无法将类型...隐式转换为...;
List要转换过去要使用Select方法;
List<Animal> lstanm2 = lstdogs.Select(d => (Animal)d).ToList();
去掉这一句的注释,注释掉前面一句,构建;
List不包含Select的定义.....;List的命名空间是using System.Collections.Generic,已经添加,为什么找不到它包含的方法?Select方法还必须包含System.Linq;
如果不包含using System.Collections.Generic,则出现CS0246;
包含了System.Collections.Generic和System.Linq,再构建;
这就不会出错; 协变和逆变参见
https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/covariance-contravariance/