• .net----泛型


    泛型的基本概念

    集合类System. Collections. ArrayList

    ArrayList list1 = new ArrayList(); //创建数组列表list1
    list1.Add(3); list1.Add(105); //向数组列表list1添加元素3、5
    int sum1 = 0;    //数组列表list1各元素之和,赋初值0
    foreach (int x in list1) sum1 += x; //求和
    Console.WriteLine(sum1);      //输出结果
    ArrayList list2 = new ArrayList(); //创建数组列表list1
    list2.Add(123); list2.Add("abc"); //向数组列表list2添加元素123、"abc"
    int sum2 = 0;                //数组列表list2各元素之和,赋初值0
    //foreach (int x in list2) sum2 += x; //求和,产生运行时异常:InvalidCastException
    Console.WriteLine(sum2);     //输出结果
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    泛型集合类System. Collection. Generic. List

    List<int> list1 = new List<int>(); //创建整型列表list2
    list1.Add(3); list1.Add(105); //向整型列表list1添加元素3、5
    
    int sum1 = 0;    //数组整型列表list1各元素之和,赋初值0
    foreach (int x in list1) sum1 += x; //求和
    Console.WriteLine(sum1);     //输出结果
    
    List<int> list2 = new List<int>();  //创建整型列表list2
    list2.Add(123);  //向整型列表list1添加整型元素123
    //list2.Add("abc"); //向整型列表list1添加字符串"abc",将导致编译错误
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    ArrayList

    • ArrayList通用化是通过在类型与通用基类型Object之间进行强制转换来实现的
    • 强制转换以及装箱和拆箱操作都会降低性能
    • 所有项都强制转换为Object,缺少编译时类型检查,在编译时无法防止客户端代码执行非法操作

    List

    • 使用List时,必须为每个实例指定其具体的数据类型
    • 编译器可以进行类型检查,从而解决了ArrayList通用化的2个主要问题,保证了程序的性能和健壮性

    泛型的定义和类型参数

    • 泛型类似于 C++ 模板,通过泛型可以定义类型安全的数据结构,而无须使用实际的数据类型

    • 泛型类和泛型方法具备可重用性、类型安全和效率

    • 泛型通过泛型参数()来定义和指定特定类型进行使用

    1. 在泛型类的声明中,需要声明泛型参数
    2.在泛型类的成员声明中,使用该泛型参数作为通用类型
    3. 在创建泛型类的实例时,则需要与泛型参数对应的实际类型

    public class Stack<T>
    {
        int pos;
        T[] data = new T[100];
        public void Push(T obj) { data[pos++] = obj; }//进栈
        public T Pop() { return data[--pos]; }        //出栈
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
     Stack<int> stack = new Stack<int>();
     stack.Push(2); stack.Push(4);   //数据进栈
     //stack.Push("a");            //编译错误
    
    • 1
    • 2
    • 3

    类型参数

    • 在泛型类型定义中,必须通过指定尖括号中的类型参数来声明类型
    • 类型参数实际上只是类型占位符
    • 在创建泛型类型的实例时,必须指定尖括号中的类型(可以是编译器识别的任何类型)
    GenericList<float> list1 = new GenericList<float>();
    GenericList<ExampleClass> list2 = new GenericList<ExampleClass>();
    GenericList<ExampleStruct> list3 = new GenericList<ExampleStruct>();
    
    • 1
    • 2
    • 3

    泛型类和泛型接口

    泛型类

    一般用于封装非特定数据类型的操作,例如集合的添加项/移除项等,与所存储数据的类型无关

    在这里插入图片描述
    泛型类的继承

    泛型接口

    泛型类共通要实现的方法、委托或事件的签名封装为泛型接口

    int[] arr = { 0, 1, 2, 3, 4 };
    List<int> list = new List<int>();
    for (int x = 5; x < 10; x++) list.Add(x);      //形成列表5、6、7、8、9
    
    Console.WriteLine("输出数组列表ArrayList的内容:");
    ProcessItems<int>(arr); 
    Console.WriteLine("输出列表List的内容:");
    ProcessItems<int>(list); 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
        static void ProcessItems<T>(IList<T> coll)
        {
            foreach (T item in coll) 
            Console.Write(item.ToString() + " ");
        }   
    
    • 1
    • 2
    • 3
    • 4
    • 5

    泛型结构

    在这里插入图片描述

    struct Point<T>
    {
        public T x;  public T y;
    }
    Point<int> pi = new Point<int>();  //泛型为int的Point
    pi.x = 2; pi.y = 2;
    Point<double> pd = new Point<double>(); //泛型为double的Point
    pd.x = 3.3; pd.y = 3.3;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    泛型方法

    使用类型参数声明的方法

    在这里插入图片描述

    static void Swap<T>(ref T lhs, ref T rhs) //声明泛型方法:两者交换
        {
            T temp; temp = lhs; lhs = rhs; rhs = temp;
        }
    
    int a = 1; int b = 2;
    Swap<int>(ref a, ref b); //调用泛型方法:指定泛型参数的类型
    double c = 1.1d; double d = 2.2d;
    Swap(ref c, ref d); //调用泛型方法:省略类型参数,编译器将推断出该参数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    泛型委托和泛型事件

    • 通过指定类型参数,可以引用泛型委托

    在这里插入图片描述

    • 基于泛型委托,可以定义泛型事件
    • 此时发送方参数可以为强类型,不再需要强制转换成Object,或反向强制转换
      在这里插入图片描述

    default关键字及协变和逆变

    • 使用default关键字,对泛型参数的变量赋初值(T t = default(T);)

    • 对于引用类型会返回null;对于数值类型会返回0;对于结构,此关键字将返回初始化为零或null的每个结构成员

    协变和逆变

    在这里插入图片描述
    在这里插入图片描述

    class Person { }
    class Student : Person { }
    class MyList<T> { }
    class MySortedList<T> : MyList<T> { }
    class Flock<T> { }
    
    MyList<String> p1 = new MyList<String>();
    MySortedList<String> c1 = new MySortedList<String>();
    p1 = c1;                   //OK,派生类可直接转换为基类
    c1 = (MySortedList<String>)p1;//OK,派生类可直接转换为基类
    
    MyList<Person> p2 = new MyList<Person>();
    MyList<Student> c2 = new MyList<Student>();
    p2 = c2;               //编译错误,不同类型参数的对象之间不能转化
    c2 = (MyList<Student>)p2;//编译错误,不同类型参数的对象之间不能转化
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  • 相关阅读:
    【机器学习算法】集成学习-2 三个臭皮匠顶一个诸葛亮,弱学习器的机器学习元算法
    UDP丢包替代:用PCAP实现C/C++以太网SDR吞吐
    宝塔Linux面板命令大全
    MaxCompute 基本概念与术语
    面试官:你了解vue的diff算法吗?
    CG-34 浊度传感器 简单说明
    supervisor的配置与使用
    spring-retry使用介绍
    Python高级网络编程
    面试常见场景题智力题概率题
  • 原文地址:https://blog.csdn.net/weixin_51422230/article/details/128024366