逆变是用
in 关键字修饰的.
in 关键字修饰的类型只能用于参数.
协变是用
out 关键字修饰的.
out 关键字修饰的类型只能用于返回值.
协变
out 比较容易理解
下面是逆变
in 的例子.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication21
{
public interface IPaintable
{
ConsoleColor Color { get; set; }
}
public class Car : IPaintable
{
public ConsoleColor Color { get; set; }
}
public interface IBrush<in T> where T : IPaintable
{
void Paint(T objectToPaint, ConsoleColor color);
}
public class Brush<T> : IBrush<T> where T : IPaintable
{
public void Paint(T objectToPaint, ConsoleColor color)
{
objectToPaint.Color = color;
}
}
class Program
{
static void Main()
{
//演示接口逆变
IBrush<IPaintable> brush = new Brush<IPaintable>();
IBrush<Car> carBrush = brush;//逆变, 因为brush中的Paint函数可以接受IPaintable类型的参数. 当然也能接受Car类型的参数.
Car car = new Car();
carBrush.Paint(car, ConsoleColor.Red);
Console.WriteLine(car.Color.ToString());
//演示委托逆变
// Func的签名为:
// public delegate TResult Func<in T, out TResult>(T arg)
var fa_b2 = new Func<A, B2>(delegate(A a)
{
return new B2();
});
fa_b2(new A2());
//A2逆变, 因为fa_b2可以接收A类型的参数 当然也能接受A2类型的参数. 所有 fa看转换为fa2.
//B协变, 因为fa_b2可以返回B2类型的返回值, 返回值当然也能转换为B
Func<A2, B> fa2_b = fa_b2;
fa2_b(new A2());
}
}
class A
{
}
class A2:A
{
}
class B
{
}
class B2 :B
{
}
}