能夠參考 https://www.cnblogs.com/qixuejia/p/4383068.html 個人測試代碼以下:html
public class Animal { } public class Dog : Animal { } public class testclass { public int i = 1; } //協變和 逆變 Func<Object,bool> parent = (p)=>{Console.WriteLine(p.GetType().FullName.ToString());return true;}; Func<testclass, bool> child = parent; child(new testclass()); //Func<testclass, bool> chx = (cp) => { Console.WriteLine(cp.GetType().FullName.ToString()); return true; }; ////Func<Object, bool> phx = chx; //此句有問題 //Func<Object, bool> phx = (Func<Object, bool>)chx; //換成這句就編譯成功,但運行時出錯。 //phx(new testclass()); Func<bool, testclass> ch = (b) => { var t = new testclass(); Console.WriteLine("t.i=" + t.i); return t; }; Func<Boolean, Object> ph = ch; ph(false); List<Dog> lsdog = new List<Dog>(); //List<Animal> lsanimal = lsdog;//沒法轉換 List<Animal> lsanimal = lsdog.Select(d => { return (Animal)d; }).ToList();//能夠正常轉換,但這種作法太麻煩 List<Animal> lsanimal1 = new List<Animal>(); //List<Dog> lsdog1 = lsanimal1; //也沒法轉換 //List<T>中沒有用到in和out關鍵字,因此List<>沒有協變和逆變功能。用IEnumerable<out T>來看看 List<Animal> lsanimal2 = new List<Animal>(); IEnumerable<Animal> ieanimal = lsanimal2; //子類轉換成父接口固然成功(只不過是相同的泛型而已) //IEnumerable<Dog> iedog = ieanimal;//不成功 爲何不成功呢?由於IEnumerable<out t>中用的是out關鍵字,表明之後轉換時,只能進行輸出轉換,既然 //是輸出轉換,若是是子轉換成父(協變)就能夠成功,若是是父轉子(逆變)就不能成功。 List<Dog> lsdog2 = new List<Dog>(); IEnumerable<Dog> iedog = lsdog2;//也是相同泛型參數的子類轉換成父接口,固然成功 IEnumerable<Animal> ieanimal2 = iedog; //協變,泛型參數子轉換成父。成功 //out關鍵字指出能夠協變,in指出能夠逆變 //c#中IEnumerable<out T>,IEnumerator<out T>,IQueryable<out T>都是能夠協變的 //IComparer<in T>,ICompareable<in T>是能夠逆變的