泛型
泛型简介
泛型是C#2.0和公共语言运行库中的一个新的功能。他类似于C++中的模板。
泛型的优势
1.可以最大限度的重用代码
2.保护类型的安全
3.提高性能
例如:要实现一个两个int相交换函数,可以这样来写
但是需求变了,现在要实现两个double类型的数相交换,现在我们应该重载Swap的方法
这时我们会觉得很是麻烦,这两个方法除了参数,返回值类型不一样,其他都一样。我们能不能把他们公共部分提取出来呢?这时泛型出现了.
代码减少了,但功能却没变。这就是代码的重用.
如果我们将传入的a是一个string类型,编译器就会报错
如果是集合的话就不会报错,直到运行时才会出现错误
这就保护类型的安全。
我们知道,添加到集合中的任何引用的或者值类型都将隐式的向上强制转换为Object。如果是值类型在添加到集合中必须进行装箱操作,在进行检索时会进行拆箱操作。在对大型集合进行多次访问时,会非常的降低性能。
泛型的名字一般用字母T作为前缀
泛型约束
在定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的类型种类施加限制.约束用关键字where
例如:首先创建一个Employee的类
public class Employee { private int id; private string name; public Employee(int i, string s) { this.id = i; this.name = s; } public int Id { get { return id; } set { id = value; } } public string Name { get { return name; } set { name = value; } } }
然后创建一个泛型类带Employee的约束
public class GenericList<T> where T:Employee { private class Node { private Node next; private T data; public Node(T t) { next = null; data = t; } public Node Next { get { return next; } set { next = value; } } public T Data { get { return data; } set { data = value; } } } private Node head; public GenericList() { head = null; } public void AddHead(T t) { Node n = new Node(t); n.Next = head; head = n; } public IEnumerator<T> GetEnumerator() { Node current = head; while (current != null) { yield return current.Data; current=current.Next; } } public T FindFirstOccurrence(string s) { Node current = head; T t = null; while (current != null) { if (current.Data.Name ==s) { t = current.Data; break; } else { current = current.Next; } } return t; } }
客户端代码
static void Main(string[] args) { GenericList<Employee> e = new GenericList<Employee>(); e.AddHead(new Employee(1,"cjn")); e.AddHead(new Employee(2,"wan")); e.AddHead(new Employee(3,"clk")); //Console.WriteLine(e.FindFirstOccurrence("wan").Name); foreach (Employee item in e) { Console.WriteLine(item.Name); } Console.ReadKey(); }
约束使得泛型类能够使用 Employee.Name 属性,因为类型为 T 的所有项都保证是 Employee 对象或从 Employee 继承的对象
泛型接口
使用泛型接口就会不需要装箱拆箱,并且保证编译时类型的安全
例如:我们要给员工排序,是按照ID排还是按照姓名排,这时我们需要泛型接口。可以随时按照想要的方式排序。
public class Employee<T> where T:IComparable<T> { private int id; private string name; public Employee(int i, string s) { this.id = i; this.name = s; } public int Id { get { return id; } set { id = value; } } public string Name { get { return name; } set { name = value; } } public bool Compare(T t1, T t2) { if (t1.CompareTo(t2) < 0) { return false; } else { return true; } } }
static void Main(string[] args) { Employee<int> e1 = new Employee<int>(1, "cjn"); Employee<int> e2 = new Employee<int>(2, "wan"); Console.WriteLine(e1.Compare(e1.Id,e2.Id)); }
泛型委托
例如:
public delegate T Del<T>(T a, T b); public class AddFunction { public int Add(int a, int b) { return a + b; } public double Add(double a, double b) { return a + b; } }
private static void Main(string[] args) { AddFunction add = new AddFunction(); Del<int> iDel = new Del<int>(add.Add); Del<double> dDel = new Del<double>(add.Add); Console.WriteLine(iDel(2,3)); Console.WriteLine(dDel(2.3, 3.2)); }
Func委托和Action委托其实是对泛型委托的一个封装。前者有返回值,后者没有返回值。
private static void Main(string[] args) { AddFunction add = new AddFunction(); Func<int, int, int> iDel = add.Add; Func<double, double, double> dDel = add.Add; Console.WriteLine(iDel(2,3)); Console.WriteLine(dDel(2.3, 3.2)); }
参考文献: MSDN
评论