天天看點

Unity 基礎之 Where限制與協變、逆變

限制 描述
where T: struct 類型參數必須為值類型
where T : class 類型參數必須為引用類型
where T : new() 類型參數必須有一個公有、無參的構造函數。當于其它限制聯合使用時,new()限制必須放在最後。
where T : <base class name> 類型參數必須是指定的基類型或是派生自指定的基類型
where T : <interface name> 類型參數必須是指定的接口或是指定接口的實作。可以指定多個接口限制。接口限制也可以是泛型的

示例

Unity 基礎之 Where限制與協變、逆變
Play函數傳入的參數必須滿足
  • 參數為引用類型
  • 必須是CustomClass01的子類或者派生類
  • 必須含有無參構造函數
  • 必須繼承Iplay接口
public class CustomClass01
{
    public int id;
}
public interface IPlay
{
    void PlayGame();
}

public class CustomGeneric
{

    public void Play<T>(T parameter) where T : CustomClass01, IPlay,new()
    {
        int Tempi = parameter.id;
        parameter.PlayGame();
        parameter = null;
    }
}
           

協變&&逆變

在具有繼承關系的兩個類 Father(基類)和Son(派生類)中,會出現如下編譯錯誤
Unity 基礎之 Where限制與協變、逆變

正常泛型解決辦法

Unity 基礎之 Where限制與協變、逆變
List<Father> FatherList3 = new List<Son>().Select(c => (Father)c).ToList();
           

但是使用協變和逆變可解決上面的問題

Unity 基礎之 Where限制與協變、逆變
協變與逆變也有他們對應的限制
  • 協變 out 隻能是傳回結果 修飾傳回值
  • 逆變 in 隻能是參數 修飾傳入參數
  • 協變逆變 隻能放在接口或者委托的泛型參數前面
相應全部代碼
/// <summary>
    /// .net4.0
    /// 隻能放在接口或者委托的泛型參數前面
    /// out 協變covariant    修飾傳回值 
    /// in  逆變contravariant  修飾傳入參數
    /// </summary>
    public class Test
    {
        public static void Show()
        {
            {
                Father bird1 = new Father();
                Father bird2 = new Son();
                Son Son1 = new Son();
                //Son Son2 = new Father();
            }

            {
                List<Father> birdList1 = new List<Father>();
                //List<Father> FatherList2 = new List<Son>();


                List<Father> FatherList3 = new List<Son>().Select(c => (Father)c).ToList();
            }
            {
                //協變
                IEnumerable<Father> FatherList1 = new List<Father>();
                IEnumerable<Father> FatherList2 = new List<Son>();

                Func<Father> func = new Func<Son>(() => null);

                ICustomerListOut<Father> customerList1 = new CustomerListOut<Father>();
                ICustomerListOut<Father> customerList2 = new CustomerListOut<Son>();
            }
            {//逆變
                ICustomerListIn<Son> customerList2 = new CustomerListIn<Son>();
                ICustomerListIn<Son> customerList1 = new CustomerListIn<Father>();

                ICustomerListIn<Father> FatherList1 = new CustomerListIn<Father>();
                FatherList1.Show(new Son());
                FatherList1.Show(new Father());

                Action<Son> act = new Action<Father>((Father i) => { });
            }


            {
                IMyList<Son, Father> myList1 = new MyList<Son, Father>();
                IMyList<Son, Father> myList2 = new MyList<Son, Son>();//協變
                IMyList<Son, Father> myList3 = new MyList<Father, Father>();//逆變
                IMyList<Son, Father> myList4 = new MyList<Father, Son>();//逆變+協變
            }
        }
    }

    public class Father
    {
        public int Id { get; set; }
    }
    public class Son : Father
    {
        public string Name { get; set; }
    }

    /// <summary>
    /// 逆變in隻能是參數
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface ICustomerListIn<in T>
    {
        void Show(T t);
    }

    public class CustomerListIn<T> : ICustomerListIn<T>
    {
        public void Show(T t)
        {
        }
    }

    /// <summary>
    /// out 協變 隻能是傳回結果
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface ICustomerListOut<out T>
    {
        T Get();
    }

    public class CustomerListOut<T> : ICustomerListOut<T>
    {
        public T Get()
        {
            return default(T);
        }
    }

    public interface IMyList<in inT, out outT>
    {
        void Show(inT t);
        outT Get();
        outT Do(inT t);

        ////out 隻能是傳回值   in隻能是參數

    }

    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);
        }
    }
           

繼續閱讀