标签:
泛型使类型参数化,从而实现了算法上的代码重用。
同时由于去掉了转换中装箱和拆箱的操作,使用泛型还可以提高程序的运行速度。
我们先看看C#自带的使用了泛型的类:
1 using System.Collections.Generic; 2 3 namespace Study 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 List<int> list1 = new List<int>(); 10 list1.Add(100); 11 int i = list1[0]; 12 13 List<string> list2 = new List<string>(); 14 list2.Add("Hello"); 15 string s = list2[0]; 16 } 17 } 18 }
通过使用泛型,我们可以重复利用List提供的功能,而不用每个类型对应去写一个List的类。
下面我们自己使用泛型编写一个简单的类,如下:
1 using System; 2 3 namespace Study 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 Test<int> test1 = new Test<int>(); 10 test1.myValue = 100; 11 Console.WriteLine(test1.myValue); 12 13 Test<string> test2 = new Test<string>(); 14 test2.myValue = "Hello"; 15 Console.WriteLine(test2.myValue); 16 } 17 } 18 19 public class Test<T> 20 { 21 private T _myValue; 22 23 public T myValue 24 { 25 set { _myValue = value; } 26 get { return _myValue; } 27 } 28 } 29 }
Test类中的尖括号里面的T即为泛型,其可以表示任意的类型。
我们上面示例中的T可以使用任意的类型,那么如果我们只希望T是某类型或某类型的子类该怎么办呢?
public class Test<T> where T : IComparable
如果这样写,则表示T必须是实现了IComparable接口的对象。
多个类型的写法如下:
public class Test<T, K> where T : IComparable where K : ICloneable
如上所示,一个类型如果要添加约束就需要写一个where进行对应,所以有多个就会有多个where关键字出现。
如果需要使用new创建一个类型,则需要在约束里添加new()的字符串,如下:
1 using System; 2 3 namespace Study 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 Test<Data> test1 = new Test<Data>(); 10 Console.WriteLine(test1.myComparable.s); 11 12 Console.Read(); 13 } 14 } 15 16 public class Test<T> where T : IComparable, new() 17 { 18 private T _myComparable; 19 20 public T myComparable 21 { 22 set { _myComparable = value; } 23 get { return _myComparable; } 24 } 25 26 public Test() 27 { 28 _myComparable = new T(); 29 } 30 } 31 32 public class Data : IComparable 33 { 34 public string s = "Hello World!"; 35 36 public int CompareTo(object obj) 37 { 38 return 0; 39 } 40 } 41 }
但是如果是值类型,则不需要这么写,但是要约束T为值类型,如下:
1 using System; 2 3 namespace Study 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 Test<int> test1 = new Test<int>(); 10 Console.WriteLine(test1.myComparable); 11 12 Console.Read(); 13 } 14 } 15 16 public class Test<T> where T : struct 17 { 18 private T _myComparable; 19 20 public T myComparable 21 { 22 set { _myComparable = value; } 23 get { return _myComparable; } 24 } 25 26 public Test() 27 { 28 _myComparable = new T(); 29 } 30 } 31 }
当我们需要对泛型T置空时不能直接写“xxx=null;”因为只有当 T 为引用类型时,语句 t = null 才有效;只有当 T 为数值类型而不是结构时,语句 t = 0 才能正常使用。所以我们使用default关键字就可以解决这个问题,如下:
_myComparable = default(T);
子类也有相同的泛型时:
1 public class A<T> 2 { } 3 4 public class B<T> : A<T> 5 { }
当然,你可以使用另外的名称,只要能对应上即可:
1 public class A<T> 2 { } 3 4 public class B<K> : A<K> 5 { }
子类指定好类型:
1 public class A<T> 2 { } 3 4 public class B : A<string> 5 { }
子类添加新类型:
1 public class A<T> 2 { } 3 4 public class B<T, K> : A<T> 5 { }
如果要在方法上添加类上没有指定的类型,可以直接在方法上添加泛型:
1 using System; 2 3 namespace Study 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 Test<int> test = new Test<int>(); 10 Console.WriteLine(test.Func<string>("Hello")); 11 12 Console.Read(); 13 } 14 } 15 16 public class Test<T> 17 { 18 public K Func<K>(K k) 19 { 20 return k; 21 } 22 } 23 }
委托上也可以使用泛型,定义方法和在方法上使用泛型一致,如下:
1 using System; 2 3 namespace Study 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 new Test(); 10 11 Console.Read(); 12 } 13 } 14 15 public class Test 16 { 17 public delegate T add<T>(T a, T b); 18 19 public Test() 20 { 21 add<int> func1 = AddInt; 22 Console.WriteLine(func1(100, 23)); 23 24 add<float> func2 = AddFloat; 25 Console.WriteLine(func2(1.2f, 0.03f)); 26 } 27 28 private int AddInt(int a, int b) 29 { 30 return a + b; 31 } 32 33 private float AddFloat(float a, float b) 34 { 35 return a + b; 36 } 37 } 38 }
泛型接口的使用和泛型类一致,大家可以查看微软自己的文档:https://msdn.microsoft.com/zh-cn/library/kwtft8ak(VS.80).aspx
泛型同样可以使用在静态字段和方法中,由于静态字段和方法在内存中始终只存在一个,所以当我们使用了泛型的时候,编译器会帮我们自动生成对应的方法。
泛型静态的使用和动态一致就跳过不说了。
我们在调用泛型方法时可以省略泛型类型的书写,完全交由编译器根据我们的类型来进行判断,这样可以减小代码量同时也更清晰:
1 using System; 2 3 namespace Study 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 //没有类型推断 10 Console.WriteLine(CompareTo<int>(100, 100)); 11 12 //使用类型推断 13 Console.WriteLine(CompareTo(12.3f, 12.33f)); 14 Console.WriteLine(CompareTo(‘a‘, ‘a‘)); 15 16 Console.Read(); 17 } 18 19 private static int CompareTo<T>(T a, T b) where T : IComparable 20 { 21 return a.CompareTo(b); 22 } 23 } 24 }
标签:
原文地址:http://www.cnblogs.com/hammerc/p/4608349.html