C# 泛型
C#中有泛型类、泛型方法、泛型接口、泛型委托。下面先介绍前3种类型。
1.泛型类、泛型方法:
1 /// <summary> 2 /// 泛型类和泛型方法 3 /// </summary> 4 /// <typeparam name="T"></typeparam> 5 class MyClass<T> 6 { 7 public void Say(T msg) 8 { 9 Console.WriteLine(msg); 10 } 11 }
实例化这个类的时候,代码如下:
1 MyClass<string> mc1 = new MyClass<string>(); 2 mc1.Say("yzk"); 3 4 MyClass<int> mc2 = new MyClass<int>(); 5 mc2.Say(20);
可以看到Say()方法中的参数类型早在实例化MyClass时就约束好了。
上面的代码中是把泛型方法写在泛型类中了,也可以把泛型方法写在普通类中。
1 /// <summary> 2 /// 普通类中的泛型方法 3 /// </summary> 4 class MyClass1 5 { 6 public string Name { get; set; } 7 public int Age { get; set; } 8 public void Say<T>(T msg) 9 { 10 Console.WriteLine(msg); 11 } 12 }
实例化这个类的时候,代码如下:
1 MyClass1 mc1 = new MyClass1(); 2 mc1.Name = "yzk"; 3 mc1.Age = 18; 4 mc1.Say<int>(10); 5 mc1.Say<string>("hello"); 6 mc1.Say<string>(mc1.Name);
可以看到,在调Say方法的时候,<>中写什么类型,后面的参数就必须是什么类型。
2.泛型接口
1 class Person:IComparable<Person> 2 { 3 public string Name { get; set; } 4 public int Age { get; set; } 5 6 public int CompareTo(Person other) 7 { 8 return other.Age - this.Age; 9 } 10 }
上面的代码,首先让Person类实现了泛型的IComparable接口,可以看到里面的CompareTo方法参数也是Person类型,就不用再转换other了,这是实现泛型接口的好处。与之类似的还有IComparer<T>接口,看下面2个比较器:
1 class SortByName:IComparer<Person> 2 { 3 4 public int Compare(Person x, Person y) 5 { 6 return y.Name.Length - x.Name.Length; 7 } 8 } 9 10 class SortByAge:IComparer<Person> 11 { 12 13 public int Compare(Person x, Person y) 14 { 15 return x.Age - y.Age; 16 } 17 }
泛型中的类型推断,代码如下:
1 /// <summary> 2 /// 普通类中的泛型方法 3 /// </summary> 4 class MyClass1 5 { 6 public string Name { get; set; } 7 public int Age { get; set; } 8 public void Say<T>(T msg) 9 { 10 Console.WriteLine(msg); 11 } 12 }
但是在使用的时候,是这个样子的:
1 MyClass1 mc1 = new MyClass1(); 2 mc1.Name = "yzk"; 3 mc1.Age = 18; 4 mc1.Say(10); 5 mc1.Say("hello"); 6 mc1.Say(mc1.Name);
可以看到,虽然Say方法是泛型的,但是调用的时候,不写参数类型,也能自动推断,这就是泛型中的类型推断。
关于泛型方法重载的问题:
1 class MyClass4 2 { 3 //如果在MyClass4写了泛型(MyClass4<T>),那么下面的Show方法可以写成这个样子:Show(T msg),不必要写<T> 4 public void Show<T>(T msg) 5 { 6 Console.WriteLine(msg); 7 } 8 9 public void Show(string msg) 10 { 11 Console.WriteLine(msg); 12 } 13 }
在实例化上面的类的时候,我们这么写:
1 MyClass4 mc4 = new MyClass4(); 2 mc4.Show("abc");
那么这个Show到底是调用了泛型方法,还是普通方法呢?且看编译器是如何编译的
new MyClass4().Show("abc");
编译器(遵循简单方便原则)看到有不带泛型的方法就直接调用了。而如果这么写就是调用泛型方法:
mc4.Show<string>("abc");
编译后的代码如下:
new MyClass4().Show<string>("abc");
泛型约束:
在写泛型的时候,可以约束泛型必须是某个类型或继承至某个类型或者实现某个接口,语法如下:
1 class MyClass<T,K,V,w,Y,D> 2 where T:struct //约束T必须是值类型; 3 where K:class //约束K必须是引用类型。 4 where V:Icomparable //约束V必须是实现Icomparable接口的类型或其子类类型. 5 where w:Person //约束w必须是Person类型或其子类类型. 6 where Y:K //约束Y必须是K类型或其子类类型。 7 where D:new() //约束参数必须有无参的公共构造函数。放在最后。