C#泛型
今天就邵志东老师所讲的Windows编程,记录点内容:
• 泛型允许类、接口、结构、委托和方法通过它们所存储和操作的数据的类型来指定类型。
• 这些类和方法将一个或多个类型的指定推迟到客户端代码声明并实例化该类或方法的时候。
• 和使用object类相比,泛型降低了装箱和拆箱的负担,减少了类型转换所带来的错误
• 使用泛型类型可以最大限度地重用代码、保护类型的安全以及提高性能。
• 泛型最常见的用途是创建集合类。
下面通过一个小Demo来说明一下泛型的使用已经泛型与Object的区别
2 using System.Collections.Generic;
3 using System.Text;
4
5 namespace GenericsDemo
6 {
7 public class StackObj
8 {
9 object[] items = new object[100];//使用的时候可以存放各种类型
10 int count=0;
11 public void Push(object item)
12 {
13 items[count] = item;
14 count++;
15 }
16 public object Pop()
17 {
18 return items[count - 1];
19
20 }
21 }
22 public class Stack<T>
23 {
24 T[] items = new T[100];
25 int count;
26 public void Push(T item)
27 {
28 items[count] = item;
29 count++;
30 }
31 public T Pop() { return items[count - 1]; }
32 }
33 class Program
34 {
35 static void Main(string[] args)
36 {
37 StackObj stack = new StackObj();
38 stack.Push(3);
39 int i = (int)stack.Pop();
40 //string s = (string)stack.Pop();//编译通过,但运行会报错,不利于我们查找错误
41 Stack<int> stackInt = new Stack<int>()
42 stackInt.Push(3);
43 int s = (int)stackInt.Pop();
44 //string s = (string)stackInt.Pop();//编译 不通过,提示错误讯息
45 Stack<string> stackString = new Stack<string>();
46 Stack<double> stackdouble = new Stack<double>();
47
48 }
49 }
50 }
51 说明:上面的Demo中分别定义了StackObj,以及泛型类Stack<T>。
C#泛型继承:
C#除了可以单独声明泛型类型(包括类与结构)外,也可以在基类中包含泛型类型的声明。但基类如果是泛型类,它的类型要么以实例化,要么来源于子类(同样是泛型类型)声明的类型参数,看如下类型
class C<U,V>
class D:C<string,int>
class E<U,V>:C<U,V>
class F<U,V>:C<string,int>
class G:C<U,V> //非法
E类型为C类型提供了U、V,也就是上面说的来源于子类
F类型继承于C<string,int>,个人认为可以看成F继承一个非泛型的类
G类型为非法的,因为G类型不是泛型,C是泛型,G无法给C提供泛型的实例化
泛型类型的成员:
泛型类型的成员可以使用泛型类型声明中的类型参数。但类型参数如果没有任何约束,则只能在该类型上使用从System.Object继承的公有成员。
泛型接口:
泛型接口的类型参数要么已实例化,要么来源于实现类声明的类型参数
泛型委托:
泛型委托支持在委托返回值和参数上应用参数类型,这些参数类型同样可以附带合法的约束
delegate bool MyDelegate<T>(T value);
class MyClass
{
static bool F(int i){...}
static bool G(string s){...}
static void Main()
{
MyDelegate<string> p2 = G;
MyDelegate<int> p1 = new MyDelegate<int>(F);
}
}
泛型方法:
1、C#泛型机制只支持“在方法声明上包含类型参数”——即泛型方法。
2、C#泛型机制不支持在除方法外的其他成员(包括属性、事件、索引器、构造器、析构器)的声明上包含类型参数,但这些成员本身可以包含在泛型类型中,并使用泛型类型的类型参数。
3、泛型方法既可以包含在泛型类型中,也可以包含在非泛型类型中。
泛型方法声明:如下
public static int FunctionName<T>(T value){...}
泛型方法的重载:
public void Function1<T>(T a);
public void Function1<U>(U a);
这样是不能构成泛型方法的重载。因为编译器无法确定泛型类型T和U是否不同,也就无法确定这两个方法是否不同
public void Function1<T>(int x);
public void Function1(int x);
这样可以构成重载
public void Function1<T>(T t) where T:A;
public void Function1<T>(T t) where T:B;
这样不能构成泛型方法的重载。因为编译器无法确定约束条件中的A和B是否不同,也就无法确定这两个方法是否不同
泛型方法重写:
在重写的过程中,抽象类中的抽象方法的约束是被默认继承的。如下:
abstract class Base
{
public abstract T F<T,U>(T t,U u) where U:T;
public abstract T G<T>(T t) where T:IComparable;
}
class MyClass:Base
{
public override X F<X,Y>(X x,Y y){...}
public override T G<T>(T t) where T:IComparable{}
}
对于MyClass中两个重写的方法来说
F方法是合法的,约束被默认继承
G方法是非法的,指定任何约束都是多余的