zoukankan      html  css  js  c++  java
  • 泛型

    一,什么是泛型
    1.这是一个Int类型的集合
    public class IntList
        {
            int[] arr;
            int count;
    
            /// <summary>
            /// 获取已储存的元素的个数
            /// </summary>
            public int Count
            {
                get { return count; }
            }
    
            public IntList(int length)
            {
                arr = new int[length];
            }
    
            #region 1.0 向集合中 追加元素 +void Add(int ele)
            /// <summary>
            /// 向集合中 追加元素
            /// </summary>
            /// <param name="ele"></param>
            public void Add(int ele)
            {
                //判断当前已添加元素的个数 是否 大于 数组的容量
                if (count >= arr.Length)
                {
                    //创建 2倍 的新数组
                    int[] arrNew = new int[arr.Length * 2];
                    //将arr 里的 数据 复制到 新数组中(从新数组的第0个位置开始存放)
                    arr.CopyTo(arrNew, 0);
                    //将新数组的引用 设置给 arr
                    arr = arrNew;
                }
                //将元素 加入到 数组中
                arr[count] = ele;
                //元素总个数 +1
                count++;
            } 
            #endregion
    
            #region 2.0 索引器  +int this[int index]
            public int this[int index]
            {
                get
                {
                    if (index >= arr.Length)
                    {
                        throw new System.Exception("数组下标越界!");
                    }
                    else
                    {
                        return arr[index];
                    }
                }
    
                set
                {
                    if (index >= arr.Length)
                    {
                        throw new System.Exception("数组下标越界!");
                    }
                    else
                    {
                        arr[index] = value;
                    }
                }
            } 
            #endregion
    
    
    2.这是一个String类型集合
    public class StringList
        {
            string[] arr;
            int count;
    
            /// <summary>
            /// 获取已储存的元素的个数
            /// </summary>
            public int Count
            {
                get { return count; }
            }
    
            public StringList(int length)
            {
                arr = new string[length];
            }
    
            #region 1.0 向集合中 追加元素 +void Add(int ele)
            /// <summary>
            /// 向集合中 追加元素
            /// </summary>
            /// <param name="ele"></param>
            public void Add(string ele)
            {
                //判断当前已添加元素的个数 是否 大于 数组的容量
                if (count >= arr.Length)
                {
                    //创建 2倍 的新数组
                    string[] arrNew = new string[arr.Length * 2];
                    //将arr 里的 数据 复制到 新数组中(从新数组的第0个位置开始存放)
                    arr.CopyTo(arrNew, 0);
                    //将新数组的引用 设置给 arr
                    arr = arrNew;
                }
                //将元素 加入到 数组中
                arr[count] = ele;
                //元素总个数 +1
                count++;
            } 
            #endregion
    
            #region 2.0 索引器  +int this[int index]
            public string this[int index]
            {
                get
                {
                    if (index >= arr.Length)
                    {
                        throw new System.Exception("数组下标越界!");
                    }
                    else
                    {
                        return arr[index];
                    }
                }
    
                set
                {
                    if (index >= arr.Length)
                    {
                        throw new System.Exception("数组下标越界!");
                    }
                    else
                    {
                        arr[index] = value;
                    }
                }
            } 
            #endregion
    当我们操作这些集合的时候
    IntList intList = new IntList(3);
                intList.Add(9);
                intList.Add(19);
                intList.Add(59);
    
                for (int i = 0; i < intList.Count; i++)
                {
                    Console.WriteLine(intList[i]);
                }
    
                StringList stringList = new StringList(3);
                stringList.Add("9a");
                stringList.Add("19b");
                stringList.Add("59c");
    
                for (int i = 0; i < stringList.Count; i++)
                {
                    Console.WriteLine(stringList[i]);
                }

    会发现变得只是类型,这样重复的类型变换有什么办法解决了,这就需要用到泛型

    /// <summary>
        /// 自定义泛型集合类,带泛型参数
        /// </summary>
        /// <typeparam name="MyType">集合的元素类型</typeparam>
        public class MyGenericList<MyType>
    {
            MyType aValue;
            MyType[] arr;
            int count;
            //int a = MyType;
    
            #region 获取已储存的元素的个数 +int Count
            /// <summary>
            /// 获取已储存的元素的个数
            /// </summary>
            public int Count
            {
                get { return count; }
            } 
            #endregion
    
            public MyGenericList(int length)
            {
                arr = new MyType[length];
            }
    
            #region 1.0 向集合中 追加元素 +void Add(MyType ele)
            /// <summary>
            /// 向集合中 追加元素
            /// </summary>
            /// <param name="ele"></param>
            public void Add(MyType ele)
            {
                //判断当前已添加元素的个数 是否 大于 数组的容量
                if (count >= arr.Length)
                {
                    //创建 2倍 的新数组
                    MyType[] arrNew = new MyType[arr.Length * 2];
                    //将arr 里的 数据 复制到 新数组中(从新数组的第0个位置开始存放)
                    arr.CopyTo(arrNew, 0);
                    //将新数组的引用 设置给 arr
                    arr = arrNew;
                }
                //将元素 加入到 数组中
                arr[count] = ele;
                //元素总个数 +1
                count++;
            } 
            #endregion
    
            #region 2.0 索引器  +MyType this[int index]
            public MyType this[int index]
            {
                get
                {
                    if (index >= arr.Length)
                    {
                        throw new System.Exception("数组下标越界!");
                    }
                    else
                    {
                        return arr[index];
                    }
                }
    
                set
                {
                    if (index >= arr.Length)
                    {
                        throw new System.Exception("数组下标越界!");
                    }
                    else
                    {
                        arr[index] = value;
                    }
                }
            } 
            #endregion
    现在调用则可以变成
    MyGenericList<int> intList = new MyGenericList<int>(3);
                intList.Add(9);
                intList.Add(19);
                intList.Add(59);
    
                for (int i = 0; i < intList.Count; i++)
                {
                    Console.WriteLine(intList[i]);
                }
    string 类型的则可以
      MyGenericList<string> stringList = new MyGenericList<string>(3);
                stringList.Add("9a");
                stringList.Add("19b");
                stringList.Add("59c");
    
                for (int i = 0; i < stringList.Count; i++)
                {
                    Console.WriteLine(stringList[i]);
                }
    MyType只是相当于一个占位符,用的时候用具体的类型来替换即可。他只能是一个类型,不能是具体的值。
    泛型是指的带类型参数的类,而不是类型参数本身。如public class MyList<T>{….}其中的MyList就是泛型,而T是类型参数。
    泛型参数可以有多个,比如MyList<T,MyType>也是可以的
    实例化一个引用类型的泛型,它在内存中分配的大小是一样的。
    实例化一个值类型的泛型,它在内存中分配的大小是不一样的。
    尽管如此,CLR还是为每个不同的类型参数创建了不同的泛型类版本。       

    二.泛型的继承

    继承一个泛型类时,必须为其传递泛型参数!

    public class Father<k,v>{}//父类

    定义子类时直接为父类泛型参数赋值
    public class Son:Father<int,string>
     
    定义子类时把子类泛型参数赋给父类泛型参数
    public  class Son<w,y>:Father<int,string>
     
    public  class Son:Father<k,v>
    这种是错误的,因为K,V不存在
     
    三.泛型约束
     public class MyGenericDog<T> 
            where T:new()//约束 传给 T 的类 必须包含一个 无参的构造函数
        {
            T t;
            public MyGenericDog()
            {
                t = new T();
            }
    }

    在使用时必须保证类有一个无参的构造函数

     private void btnNewT_Click(object sender, EventArgs e)
            {
                MyGenericDog<LittleDog> list = new MyGenericDog<LittleDog>();
            }
    public class LittleDog
        {
            public LittleDog()
            {
            }
    
            public LittleDog(string str)
            {
            }
      }

    四.用来约束泛型参数 必须是某个类 或者某个类的子类

    class Dog
    {
        public void Shout(){}
    }
    class Cat
    {
        public void Walk(){}
    }
    class House<TPet,TPet2>where TPet:Dog where TPet2:Cat
    {
        public c(TPet p,TPet2 p2)
       {
           p1.Shout();
           p2.Walk();
       }
    }

    1.一个泛型参数不允许多个基类约束,不能写成

    class House<TPet,TPet2>where TPet:Dog where TPet:Cat
    因为不可能既是狗,又是猫。
    2.不能为密封类指定基类约束(string) 密封类即为私有类。即sealed这种不能继承的类。
    3.也不能用nullable<T>
    五.用来约束泛型参数必须是值类型或者引用类型
    public struct A{}
    public class B{}
    public class C<T> where T:struct  值类型
    {
    }
    public class C2<T> where T:class  引用类型
    {
    }
    
    比如上面的如果使用c<person>就会报错
    六.泛型方法
    public void Test<k>() where k:new()
    {
    }

    K可以用在三个地方:

    1.参数

    public void Test<k>(k a) {
    }

    2.可以在方法体内用到

    public void Test<k>() where k:new()
    {
       k k1=new k();
    }

    3.可以当返回值

    public K Test<k>() where k:new()
    {
       return k;
    }

    七.泛型方法的重载

    void sayA()
                {
                }
               void sayA<T>()
                {
                }
               void sayA<K>()
                {
                }

    在使用时可以看到智能提示出现两个方法say,say<>说明他们不构成重载

               void sayA<T>()
                {
                }
               void sayA<K>()
                {
                }
    这样是不行的,因为泛型方法只是个占位符,编译器会认为是同一个方法

    八.泛型方法重写

    6@%9ZGPL460]WM}N3PO5T3O

    子类当中约束where k:class是不能在子类中重写。而where k:new()不需要些,从父类中继承过来了。

  • 相关阅读:
    OA常见问题和解决方案
    如何用Visio画venn(维恩)图
    小谈SQL表的连接
    记一次视图的应用
    常用sql语句备份
    EF中关系映射问题
    .net core 2.0的一次奇特经历
    .net core 下的Area注册
    win 10+ iis 10 部署.net core 1.1 web api
    AutoMapper差异内容备份
  • 原文地址:https://www.cnblogs.com/automation/p/3416393.html
Copyright © 2011-2022 走看看