using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyGeneric.CC { /// <summary> /// 逆变(contravariant)与协变(covariant):只能用在接口和委托上面 /// out “协变”->”和谐的变”->”很自然的变化”->string->object :协变。 负责修饰返回值 /// in “逆变”->”逆常的变”->”不正常的变化”->object->string 逆变。 负责修饰参数 /// </summary> public class CCTest { public static void Show() { Child child = new Child(); Parent parent = new Parent(); Parent parent77 = new Child(); Parent parent88 = (Parent)child; { List<Parent> parentList = new List<Parent>(); //List<Parent> parentList3 = new List<Child>();//需要转换才行 List<Parent> parentList1 = new List<Child>().Select(c => (Parent)c).ToList();//需要自己转换 IEnumerable<Parent> parentList2 = new List<Child>();//协变 只能是返回值,返回的Child必然是Parent的 Action<Child> act = new Action<Child>(c => { });//按说都是child才行 Action<Child> act1 = new Action<Parent>(c => { });//l使用act1的时候,参数只能是Child,必然满足lambda表达式对parent的类型要求 act(child); act1(child); } { //增强了接口、委托的适用范围,同时保证了类型安全 IMyList<Child, Parent> list1 = new MyList<Child, Parent>(); { list1.Show(child); Parent parent1 = list1.Get(); Parent parent2 = list1.Do(child); } IMyList<Child, Parent> list2 = new MyList<Child, Child>(); { list2.Show(child); Parent parent1 = list2.Get(); Parent parent2 = list2.Do(child); } IMyList<Child, Parent> list4 = new MyList<Parent, Parent>(); { list4.Show(child); Parent parent1 = list4.Get(); Parent parent2 = list4.Do(child); } IMyList<Child, Parent> list3 = new MyList<Parent, Child>(); { list3.Show(child); Parent parent1 = list3.Get(); Parent parent2 = list3.Do(child); } } } } public class Parent { } public class Child : Parent { } public interface IMyList<in inT, out outT> { void Show(inT t); outT Get(); outT Do(inT t); ////out 只能是返回值 in只能是参数 //void Show1(outT t); //inT Get1(); } public class MyList<T1, T2> : IMyList<T1, T2> { public void Show(T1 t) { Console.WriteLine(t.GetType().Name); } public T2 Get() { Console.WriteLine(typeof(T2).Name); return default(T2); } public T2 Do(T1 t) { Console.WriteLine(t.GetType().Name); Console.WriteLine(typeof(T2).Name); return default(T2); } } }