C# 里的泛型如何使用?
答:泛型是 C# 2.0 开始引入的一种更加灵活、规范的数据操作机制,看例子:
class Student{}
假设有学生对象需要存入集合,再提取出来
ArrayList list = new ArrayList(); //1、实例化 list 集合对象
Student s = new Student(); //2、实例化一个学生对象
list.Add(s); //3、将学生存入集合
Student tmp = (Student) list[0]; //4、将学生对象从集合中取出来
传统的操作方式如上。
如果,存入的是学生对象,而取出的时候错以为是老师对象,第 4 行代码可能写成:
Teacher tmp = (Teacher) list[0];
在编译时,系统不会发现这个问题,因为存入 list 的对象都会被装箱为 object ,取出的时候由 object 进行拆箱,系统没办法确定数据类型,所以,就算存入和取出的类型不一致,也不会提示错误。编译不出错,运行时肯定要出错了,因为学生对象强制转换为老师,是错误的。
那如何尽早的进行类型规范和检查呢?使用泛型。
List<Student> list = new List<Student>(); //1、实例化只能存放 Student 对象的集合
Student s = new Student(); //2、实例化一个学生对象
list.Add(s); //3、将学生存入集合
Student tmp = list[0]; //4、将学生对象从集合中取出来
注意代码的区别:
第一行:我们没有再使用 ArrayList ,而是使用了 List 泛型集合
语法:尖括号 < > 中的数据类型是在规范集合只能存入此类型数据。
第四行:因为定义时有固定的操作类型(),所以,提取 list[0] 肯定是 Student 类型的对象,免去了数据类型转换的麻烦。
那我们再使用 Teacher tmp = list[0]; 去进行错误类型的提取,程序将在编译时发现数据类型和泛型定义不一致的错误,使我们的程序更安全,更规范,同时,进出 list 集合的数据都有了类型,免去了传统集合进出数据时的装箱和拆箱的操作,提高了数据访问速度。
泛型可以更规范的定义集合中存储的数据类型,其实可以以一种模板的方式来理解:
List<Student> list = new List<Student>(); 相当于系统原有 List 集合类型是模板,我们通过模板创建了一种只能操作 Student 类型的集合。那模板的操作方式还有什么用途呢?
现在我们调用 list.Sort() 方法,对集合当中的学生对象进行排序,因为 Student 类型不是系统内置的数据类型,所以排序操作肯定是错误的。那如果需要按照我们的要求进行排序,比如按年龄排序,又该怎么做呢?
很多集合都需要有排序功能,所以系统有接口 IComparable ,来规范对象排序的操作。既然 IComparable 可以规范各种类型的排序,那就认为是一种模板,同时也就想到了泛型:
class Student : IComparable<Student> //实现 泛型 比较接口
{
private int _age;
public int Age { get ; set; } //定义年龄属性
public int CompareTo(Student other) //以泛型方式声明,所以操作对象也就是 Student
{
if(this.Age > other.Age)
return 1;
if(this.Age == other.Age)
return 0;
return -1; //大于 等于 小于 对应返回 1 / 0 / -1
}
}
这样操作 Student 类后,list.Sort() 功能也就可以通过调用 CompareTo 来对集合里的各个学生对象进行排序了。