Unity基础之C#进阶篇笔记2:泛型

Unity基础之C#进阶篇笔记2:泛型

  • 泛型
    • 1.泛型是什么
    • 2.泛型分类
    • 3.泛型类和接口
    • 4.泛型方法
    • 5.泛型的作用
    • 6.总结
    • 7.练习题
  • 泛型约束
    • 1.什么是泛型约束
    • 2.各泛型约束讲解
    • 3.约束的组合使用
    • 4.多个泛型有约束
    • 5.总结
    • 6.练习题

泛型

1.泛型是什么

    //泛型实现了类型参数化,达到代码重用目的
    //通过类型参数化来实现同一份代码上操作多种类型

    //泛型相当于类型占位符
    //定义类或方法时使用替代符代表变量类型
    //当真正使用类或者方法时再具体指定类型

2.泛型分类

    //泛型类和泛型接口
    //基本语法:
    //class 类名<泛型占位字母>
    //interface 接口名<泛型占位字母>

    //泛型函数
    //基本语法:函数名<泛型占位字母>(参数列表)

    //注意:泛型占位字母可以有多个,用逗号分开

3.泛型类和接口

    class TestClass<T>
    {
        public T value;
    }    

    class TestClass2<T1,T2,K,M,LL,Key,Value>
    {
        public T1 value1;
        public T2 value2;
        public K value3;
        public M value4;
        public LL value5;
        public Key value6;
        public Value value7;
    }

    interface TestInterface<T>
    {
        T Value
        {
            get;
            set;
        }
    }

    class Test : TestInterface<int>
    {
        public int Value { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    }

4.泛型方法

    //1.普通类中的泛型方法

    class Test2
    {
        public void TestFun<T>( T value)
        {
            Console.WriteLine(value);
        }

        public void TestFun<T>()
        {
            //用泛型类型 在里面做一些逻辑处理
            T t = default(T);
        }

        public T TestFun<T>(string v)
        {
            return default(T);
        }

        public void TestFun<T,K,M>(T t, K k, M m)
        {

        }
    }

    //2.泛型类中的泛型方法
    class Test2<T>
    {
        public T value;

        public void TestFun<K>(K k)
        {
            Console.WriteLine(k);
        }

        //这个不叫泛型方法 因为 T是泛型类申明的时候 就指定 在使用这个函数的时候 
        //我们不能再去动态的变化了
        public void TestFun(T t)
        {

        }
    }

5.泛型的作用

    //1.不同类型对象的相同逻辑处理就可以选择泛型
    //2.使用泛型可以一定程度避免装箱拆箱
    //举例:优化ArrayList
    class ArrayList<T>
    {
        private T[] array;

        public void Add(T value)
        {

        }

        public void Remove( T value)
        {

        }
    }

6.总结

    //1.申明泛型时 它只是一个类型的占位符
    //2.泛型真正起作用的时候 是在使用它的时候
    //3.泛型占位字母可以有n个用逗号分开
    //4.泛型占位字母一般是大写字母
    //5.不确定泛型类型时 获取默认值 可以使用default(占位字符)
    //6.看到<>包裹的字母 那肯定是泛型

7.练习题

	    定义一个泛型方法,方法内判断该类型为何类型,并返回类型的名称与占有的字节数
        如果是int,则返回“整形,4字节”
        只考虑以下类型
        int:整形
        char:字符
        float:单精度浮点数
        string:字符串
        如果是其它类型,则返回“其它类型”
        (可以通过typeof(类型) == typeof(类型)的方式进行类型判断)
        static string Fun<T>()
        {
            if( typeof(T) == typeof(int) )
            {
                return string.Format("{0},{1}字节", "整形", sizeof(int));
            }
            else if (typeof(T) == typeof(char))
            {
                return string.Format("{0},{1}字节", "字符", sizeof(char));
            }
            else if (typeof(T) == typeof(float))
            {
                return string.Format("{0},{1}字节", "单精度浮点数", sizeof(float));
            }
            else if (typeof(T) == typeof(string))
            {
                return string.Format("{0},{1}字节", "字符串", "?");
            }
            return "其它类型";
        }

泛型约束

1.什么是泛型约束

    //让泛型的类型有一定的限制
    //关键字:where
    //泛型约束一共有6种
    //1.值类型                              where 泛型字母:struct
    //2.引用类型                            where 泛型字母:class
    //3.存在无参公共构造函数                 where 泛型字母:new()
    //4.某个类本身或者其派生类               where 泛型字母:类名
    //5.某个接口的派生类型                  where 泛型字母:接口名
    //6.另一个泛型类型本身或者派生类型       where 泛型字母:另一个泛型字母

    // where 泛型字母:(约束的类型)

2.各泛型约束讲解

    #region 值类型约束
    class Test1<T> where T:struct
    {
        public T value;

        public void TestFun<K>(K v) where K:struct
        {

        }
    }
    #endregion

    #region 引用类型约束
    class Test2<T> where T:class
    {
        public T value;

        public void TestFun<K>(K k) where K:class
        {

        }
    }
    #endregion

    #region 公共无参构造约束
    class Test3<T> where T:new()
    {
        public T value;

        public void TestFun<K>(K k) where K : new()
        {

        }
    }

    class Test1
    {
        public Test1()
        {

        }
    }

    class Test2
    {
        public Test2(int a)
        {

        }
    }
    #endregion

    #region 类约束
    class Test4<T> where T : Test1
    {
        public T value;

        public void TestFun<K>(K k) where K : Test1
        {

        }
    }

    class Test3:Test1
    {

    }
    #endregion

    #region 接口约束
    interface IFly
    {

    }

    interface IMove:IFly
    {

    }

    class Test4:IFly
    {

    }

    class Test5<T> where T : IFly
    {
        public T value;

        public void TestFun<K>(K k) where K : IFly
        {

        }
    }
    #endregion

    #region 另一个泛型约束
    class Test6<T,U> where T : U
    {
        public T value;

        public void TestFun<K,V>(K k) where K : V
        {

        }
    }
    #endregion

3.约束的组合使用

    class Test7<T> where T: class,new()
    {

    }

4.多个泛型有约束

    class Test8<T,K> where T:class,new() where K:struct
    {

    }

5.总结

    //泛型约束:让类型有一定限制
    //class
    //struct
    //new()
    //类名
    //接口名
    //另一个泛型字母

    //注意:
    //1.可以组合使用
    //2.多个泛型约束 用where连接即可

6.练习题

1.练习题1

#region 练习题一 
    //用泛型实现一个单例模式基类

    class SingleBase<T> where T:new()
    {
        private static T instance = new T();

        public static T Instance
        {
            get
            {
                return instance;
            }
        }
    }

    class GameMgr : SingleBase<GameMgr>
    {
        public int value = 10;
    }

    class Test : SingleBase<Test>
    {
        public int value = 10;
    }

    class Test2
    {
        private static Test2 instance = new Test2();

        public int value = 10;
        private Test2()
        {

        }

        public static Test2 Instance
        {
            get
            {
                return instance;
            }
        }
    }
    #endregion

2.练习题2

#region 练习题二
    //利用泛型知识点,仿造ArrayList实现一个不确定数组类型的类
    //实现增删查改方法

    class ArrayList<T>
    {
        private T[] array;

        //当前正儿八经存了多少数
        private int count;

        public ArrayList()
        {
            count = 0;
            //一开始的容量就是16
            array = new T[16];
        }

        public void Add(T value)
        {
            //是否需要扩容
            if( count >= Capacity )
            {
                //搬家 每次 家扩容2倍
                T[] temp = new T[Capacity * 2];
                for (int i = 0; i < Capacity; i++)
                {
                    temp[i] = array[i];
                }
                //重新指向地址
                array = temp;
            }
            
            //不需要扩容 直接加
            array[count] = value;
            ++count;
        }

        public void Remove(T value)
        {
            //这个地方 不是小于数组的容量
            //是小于 具体存了几个值
            int index = -1;
            for (int i = 0; i < Count; i++)
            {
                //不能用==去判断 因为 不是所有的类型都重载了运算符 
                if( array[i].Equals(value))
                {
                    index = i;
                    break;
                }
            }
            //只要不等于-1 就证明找到了 那就去移除
            if(index != -1)
            {
                RemoveAt(index);
            }
        }

        public void RemoveAt(int index)
        {
            //索引合法不
            if( index < 0 || index >= Count )
            {
                Console.WriteLine("索引不合法");
                return;
            }

            //后面的往前放
            for (; index < Count - 1; index++)
            {
                array[index] = array[index + 1];
            }
            //把一个数移除了 后面的往前面放 那么最后一个 要移除
            array[Count - 1] = default(T);
            --count;
        }

        public T this[int index]
        {
            get
            {
                if (index < 0 || index >= Count)
                {
                    Console.WriteLine("索引不合法");
                    return default(T);
                }
                return array[index];
            }
            set
            {
                if (index < 0 || index >= Count)
                {
                    Console.WriteLine("索引不合法");
                    return;
                }
                array[index] = value;
            }
        }

        /// 
        /// 获取容量
        /// 
        public int Capacity
        {
            get
            {
                return array.Length;
            }
        }

        /// 
        /// 得到具体存了几个值
        /// 
        public int Count
        {
            get
            {
                return count;
            }
        }
    }
    #endregion

你可能感兴趣的:(Unity基础之C#进阶篇笔记)