using System;
using System.Collections.Generic;
using System.Drawing;
/*
* 协变:能够使用比原始指定的派生类型的派生程度更大的类型。
* 逆变:能够使用比原始指定的派生类型的派生类型更小的类型。
*
* 注1:只有泛型接口和泛型委托支持协变、逆变。
* 注2:协变、逆变使泛型支持多态。
*/
namespace CovariantAndContravariant
{
internal class Program
{
static void Main(string[] args)
{
Dog dog = new Dog("大黄");
Animal animal = dog;// 子类可以转换为父类
Console.WriteLine(animal.Name);
//List<Animal> animals = new List<Dog>();// 虽然Animal和Dog之间存在继承关系,但是List<Animal>和List<Dog>之间不存在继承关系,所以编译时报错
IEnumerable<Animal> _animals = new List<Dog>();// 虽然Animal和Dog之间不存在继承关系,但是List<Dog>可以转换为IEnumerable<Animal>,因为泛型接口IEnumerable<out T>支持“协变”,所以不会报错
Console.WriteLine("\r\n=================================华丽的分割线=================================\r\n");
Animal animal1 = new Animal();
//Snake snake = animal1;// 编译时报错,父类无法直接转换为子类
//Snake snake = (Snake)animal1;// 父类强制转换为子类,编译时不会报错,但运行时报错,Animal无法转换成Snake
Action<Snake> action = new Action<Animal>(s => { Console.WriteLine(s.Name); });// 虽然Animal无法转换成Snake,但是Action<Animal>可以转换为Action<Snake>,因为泛型委托Action<in T>支持“逆变”,所以不会报错
action(new Snake("小青"));
Console.WriteLine("\r\n=================================华丽的分割线=================================\r\n");
// 自定义协变
ICustomCovariant<Animal> customCovariant = new CustomCovariant<Dog>();
Dog dog1 = customCovariant.Get() as Dog;
Console.WriteLine(dog1.Name);
// 自定义逆变
ICustomContravariant<Snake> customContravariant = new CuntomContravariant<Animal>();
Animal animal2 = new Snake("小青");
customContravariant.Set(animal2 as Snake);
Console.ReadLine();
}
}
public class Animal
{
public string Name = "null";
}
public class Dog : Animal
{
/// <summary>
/// 毛发颜色
/// </summary>
public Color HairColor = Color.Yellow;
public Dog(string name)
{
Name = nameof(Dog) + "---" + name;
}
}
public class Snake : Animal
{
/// <summary>
/// 皮肤颜色
/// </summary>
public Color SkinColor = Color.Cyan;
public Snake(string name)
{
Name = nameof(Snake) + "---" + name;
}
}
#region 自定义协变
public interface ICustomCovariant<out T>// out表示给接口支持“协变”
{
T Get();
}
public class CustomCovariant<T> : ICustomCovariant<T>
{
public T Get()
{
if (typeof(T) == typeof(Dog))
{
Dog dog = new Dog("大黄---协变");
object obj = dog;
return (T)obj;
}
else
{
return default(T);
}
}
}
#endregion
#region 自定义逆变
public interface ICustomContravariant<in T>// in表示该接口支持“逆变”
{
void Set(T value);
}
public class CuntomContravariant<T> : ICustomContravariant<T>
{
public void Set(T value)
{
if (value is Snake snake)
{
snake.Name += "---逆变";
Console.WriteLine(snake.Name);
}
}
}
#endregion
}
09-28
358