1. 程式人生 > 實用技巧 >C# 泛型的協變

C# 泛型的協變

    class Program
    {
        static void Main(string[] args)
        {
            Person person = new Person();
            Person chinese2 = new Chinese();//chinese繼承自person,所以允許轉換


            List<Person> people = new List<Person>();
            //以下程式碼不允許。
            //一群中國人難道不是一群人??
            
//1、list<people>與list<chinese>沒有繼承關係。 //2、若成立,就可以向這個列表中寫入people型別資料,也可以寫入chinese型別資料,這是型別不安全的 List<Person> chineses = new List<Chinese>(); //另外一個更容易理解的例子 //所有類都是Object的子類,若這個轉換成立,那麼list裡可以有各種各樣的資料。 List<object> list = (List<object
>)people; //協變 IMyList<Person> myPeople = new MyList<Chinese>(); myPeople.Item = new Person();//協變的屬性是隻讀的,所以報錯 //協變的前提: //1、只有泛型介面和泛型委託才可以協變,詳見MyList2類 //2、協變的型別實參只能是引用型別,不能是值型別 IMyList<object
> myList1 = new MyList<int>(); } } class Person { public int ID { get; set; } public string Name { get; set; } } class Chinese: Person { public string Gender { get; set; } } /// <summary> /// c#4.0起,使用out 型別引數修飾符允許協變。 /// 協變型別引數只能是隻讀; /// out修飾符會讓編譯器驗證T是否真的只用作“輸出”,且永遠不用於形參或屬性的賦值方法 /// </summary> /// <typeparam name="T"></typeparam> interface IMyList< out T> { public T Item { get;} /// <summary> /// out 修飾的型別引數必須是隻讀,所以程式碼報錯 /// </summary> public T Item2 { get; set; } /// <summary> /// out 修飾的型別引數不能做為形參,所以程式碼報錯 /// </summary> /// <param name="t"></param> public void SetValue(T t); } /// <summary> /// 實現介面類 /// </summary> /// <typeparam name="T"></typeparam> class MyList<T> : IMyList<T> { public T Item => default(T); public T Item2 { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public void SetValue(T t) { } } /// <summary> /// 只有泛型介面和泛型委託才可以協變。泛型型別與結構永遠不可協變 /// </summary> /// <typeparam name="T"></typeparam> class MyList2<out T> { }