一、引言
前面我们学过泛型集合List,非泛型集合ArrayList,了解到创建List集合的时候,需要指定类型,并且只能存储这种类型的数据,相比ArrayList能存储各种类型的数据而言,效率更高(避免了装箱拆箱)。那我们声明List<int>集合的时候,开始为何不直接设计一个ListInt类,而要设计成List<T>呢?因为List中的方法,算法其实是一样的,这样可以避免重复,并且,如果我要在List中保存自己自定义的类的对象的时候,(比如Person),无法再像开始那样,有预见性的设计出一个ListPerson类。所以需要引入泛型。
二、泛型类
下面看一个具体的例子:
1 public class MyClass 2 { 3 public string [] Names { get; set; } 4 5 public MyClass(string [] names) 6 { 7 this.Names = names; 8 } 9 10 public void Show() 11 { 12 foreach (string item in Names) 13 { 14 Console.WriteLine(item); 15 } 16 } 17 }
在控制台程序中输出数组中的元素:
1 static void Main(string[] args) 2 { 3 4 string[] names = { "A","B","C","D"}; 5 6 MyClass mc = new MyClass(names); 7 mc.Show(); 8 9 Console.ReadKey(); 10 }
现在需求改动,想把string类型的数组改成int类型的,这时候,我们只好把MyClass中和控制台中所有关于类型的地方全部改下,但是其他地方丝毫不用改。这当然可以,只是有点麻烦,有没有其他方式,不用改动MyClass中的东西呢?
这时候可以泛型。改动后的代码如下:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 6 string[] names = { "A","B","C","D"}; 7 //MyClass<string> mc = new MyClass<string>(names); 8 9 //如果要改成Int类型的数组,只要作如下改动 10 MyClass<int> mc = new MyClass<int>(new int[] {1,2,3,4 }); 11 12 mc.Show(); 13 14 Console.ReadKey(); 15 } 16 } 17 18 public class MyClass<T> 19 { 20 public T [] Names { get; set; } 21 22 public MyClass(T [] names) 23 { 24 this.Names = names; 25 } 26 27 public void Show() 28 { 29 foreach (T item in Names) 30 { 31 Console.WriteLine(item); 32 } 33 } 34 }
这里我们能明显看到泛型的方便了。
三、泛型接口
有以上的基础,看泛型接口就可以容易了,直接上代码:
1 public interface IFlyable<T> 2 { 3 void Fly(T t); 4 }
但是要注意:
1.如果是实例类实现泛型接口,泛型接口必须指定泛型的类型:
1 public class SpiderMan : IFlyable<string> 2 { 3 public void Fly(string t) 4 { 5 Console.WriteLine(t); 6 } 7 }
2.如果是泛型类,实现泛型接口的时候必须指定泛型的类型:
1 public class SpiderMan<T> : IFlyable<T> 2 { 3 public void Fly(T t) 4 { 5 throw new NotImplementedException(); 6 } 7 }
四、泛型方法
1 public class Person 2 { 3 //方法后面加个<T>就是泛型方法 4 public void Show<T>(T t) 5 { 6 Console.WriteLine(t); 7 } 8 }
main函数中的代码:
1 Person p = new Person(); 2 p.Show("aaa");//方法名称后面不加<T>,编译器会根据传入的数据,自动推断 3 p.Show<string>("aaa");// 4 p.Show(2);
五、泛型委托
首先写几委托和方法:
1 public delegate void MDelegate(string str);
1 public delegate void IDelegate(int i); 2 public delegate void MDelegate(string str); 3 public delegate void DDelegate(double d);
方法:
1 static void M1(int i) 2 { 3 Console.WriteLine(i); 4 } 5 6 static void M2(string s) 7 { 8 Console.WriteLine(s); 9 } 10 11 static void M3(double d) 12 { 13 Console.WriteLine(d); 14 }
我们要使用MDelegate这个委托只能传入方法签名一致的方法M2,如果我想调用M1,M3方法的话,必须再写两个委托,太麻烦。
1 MDelegate m = M2; 2 m("124"); 3 4 IDelegate i = M1; 5 i(1); 6 7 DDelegate d = M3; 8 d(1.2);
但是改成泛型委托,情况就变得简单很多了
1 public delegate void DynamicDelegate<T>(T t);
用上面泛型委托,可以调用M1,M2,M3方法,如下:
1 DynamicDelegate<int> i = M1; 2 i(1); 3 4 DynamicDelegate<string> s = M2; 5 s("afsd"); 6 7 DynamicDelegate<double> d = M3; 8 d(1.2);