.net----泛型

本文深入探讨了泛型的概念,对比了非泛型集合类ArrayList与泛型集合类List<T>的性能和安全性。通过示例展示了泛型在类型安全、代码复用和效率方面的优势。泛型允许在不指定具体类型的情况下定义类、接口、方法、委托和事件,提供编译时类型检查,避免了装箱拆箱带来的性能损失。此外,还介绍了default关键字、协变和逆变的概念,强调了泛型在.NET编程中的重要性。
摘要由CSDN通过智能技术生成

泛型的基本概念

集合类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);     //输出结果

泛型集合类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",将导致编译错误

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]; }        //出栈
}
 Stack<int> stack = new Stack<int>();
 stack.Push(2); stack.Push(4);   //数据进栈
 //stack.Push("a");            //编译错误

类型参数

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

泛型类和泛型接口

泛型类

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

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

泛型接口

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

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); 
    static void ProcessItems<T>(IList<T> coll)
    {
        foreach (T item in coll) 
        Console.Write(item.ToString() + " ");
    }   

泛型结构

在这里插入图片描述

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;

泛型方法

使用类型参数声明的方法

在这里插入图片描述

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); //调用泛型方法:省略类型参数,编译器将推断出该参数

泛型委托和泛型事件

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

在这里插入图片描述

  • 基于泛型委托,可以定义泛型事件
  • 此时发送方参数可以为强类型,不再需要强制转换成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;//编译错误,不同类型参数的对象之间不能转化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

醉卧考场君莫笑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值