决定一个人富有的三个条件,一是出身,二是运气,三是努力
If you can dream it,you can do it! Nothing Impossible~

  泛型(Generic)是对CLR类型系统的扩展,用于定义未指定某些细节的类型。实际上,代码本身就是泛型。

  使用泛型可以避免以下两个常见的问题:代码冗余和困扰开发人员的含混不清的编译器错误。假设集合类SortedList是Object引用的集合,GenericSortedList<T>是任意类型的集合,使用泛型具有以下明显的优点。

  (1)类型安全

    当用户向SortedList类型的集合内添加String时,String会隐式强制转换为Object。同样,如果从该列表中检索String对象,则它必须在运行时从Object引用强制转换到String引用。这样就会造成编译时缺少类型安全,从而使编写的代码容易出错。相反,如果使用GenericSortedList<String>(T的类型被设置为String),就会使所有的添加和查找方法是用String引用。这样在编译时就可以检查元素的类型是否正确。

  (2)二进制代码重用

    为了进行维护,开发人员可以选择使用SortedList,通过从它派生SortedListOfString来实现编译时的类型安全。此方法有一个问题,那就是必须对于每个需要类型安全列表的类型都编写新代码,而这会很快变成非常费力的工作。使用GenericSortedList<T>,需要执行的全部操作就是将具有所需元素类型的类型实例化为T。泛型代码还有一个附加价值,那就是它在运行时生成,因此,对于无关元素类型的两个扩展(如GenericSortedList<String>和GenericSortedList<FileStream>)能够重新使用同一个实时(JIT)编译代码的大部分。CLR只是处理细节就可以了,从而使代码不再臃肿。

  (3)性能

    如果能在编译时进行类型检查,而不是在运行时进行检查,则显然会大大增强系统的性能。在托管代码中,引用和值之间的强制转换既会导致装箱又会导致拆箱,而且避免这样的强制转换可能会对性能产生同样的负面影响。如果对一个由一百万个整数组成的数组进行快速排序法基准测试,就会发现泛型方法比非泛型方法快得多。这是由于完全避免了对这些值进行装箱。如果针对由字符串引用组成的数组进行同样的排序,则由于无需在运行时执行类型检查,因此使用泛型方法后大大提高了性能。

  (4)清晰性

    泛型的清晰性体现在许多方面。约束是泛型的一个功能,它会禁止对泛型代码进行不兼容的扩展;使用泛型,也不再有困扰C++模板用户的含混不清的编译器错误。在GenericSortedList<T>中,集合类将有一个约束,该约束使集合类只处理可进行比较并依此进行排序的T类型。同样,通常可以使用名为类型推理的功能来调用泛型的方法,而无需使用任何特殊语法。当然,编译时类型安全可以使应用程序代码更加清晰。

  

泛型的定义

  CLR支持多种编程语言,因此,CLR泛型也有多种语法。但是,无论采用哪种语法,用一种面向CLR的语言编写的泛型代码也可以由其他面向CLR的语言编写的程序使用。

  泛型的定义代码语法为:

  [访问修饰符] [返回类型] 泛型支持类型泛型名称<类型参数列表>

   

  其中,CLR支持泛型类、结构、方法、接口和委托等。泛型名称要符合标示符的定义。尖括号表示类型参数列表,尖括号紧跟在泛型类类型或成员的名称后面。同样,在类型参数列表中有一个或多个类型参数,形式如<T,U,…>。

例1:定义一个泛型类

1 class Node <T>
2 {
3 T data;
4 Node<T>next;
5 }
6  

 

例2:定义一个泛型方法

1 void Swap<T>(ref T item1, ref T item2)
2 {
3 T temp=item1;
4 item1=item2;
5 item2=temp;
6 }
7  

 

泛型的引用

  引用泛型时,也可以将未指定的类型变成系统能够识别的指定的类型。例3和例4分别是对例1和例2的引用示例。

 

例3:引用一个泛型类

1 class Node8Bit:Node<Byte>
2 {
3
4 }
5  

例4:引用一个泛型方法

1 Decimal d1=0,d2=2;
2 Swap<Decimal>(ref d1,ref d2);

 

  通过例子可以看出,定义一个类或者方法时,可以利用泛型<T>代表任何一种类型,而在引用时再指定具体类型。在例6中,当代码调用泛型方法Swap<T>时,C#编译器会自动将定义的泛型转换为引用代码中指定的类型,从而大大简化了编程人员代码书写的工作量。

  由于泛型<T>可以代表任何一种类型,因此只定义一次方法的参数类型就能实现所有类型的引用。例如,例6中的d1可能是int型、float型等(d2同样如此),如果不使用泛型,就需要写出很多重载的Swap方法,使代码既臃肿,又不易阅读,同时也增加了编译工作量。由此可以看出,泛型的优点是显而易见的。

 

常用的泛型集合

  在.NET Framework类库中,System.Collections.Generic和System.Collections.ObjectModel命名空间中提供了很多泛型集合类。许多泛型集合类型是泛型类型的直接模拟。表1列出了常见的泛型集合类与非泛型集合类的对应关系。

表1         常见的泛型集合类及对应的非泛型集合类

1. List<T>

  List泛型类表示可通过索引访问的对象的强类型列表,提供用于对列表进行搜索、排序和操作的方法。常用方法如下。

  Add方法:将指定值的元素添加到List<>中。

  Insert方法:在列表的中间插入一个新元素。

  Contains方法:测试该列表中是否存在某个元素。

  Remove方法:从列表中移除带有指定键的元素。

  Clear方法:移除列表中的所有元素。

2. Dictionary<Tkey,Tvalue>

  Dictionary泛型类提供了一组键到一组值的映射。字典中的每个添加项都由一个值及其相关联的键组成,通过键来检索。常用方法如下:

  Add方法:将带有指定键和值的元素添加到Dictionary<,>中。

  TryGetValue方法:获取与指定键相关联的值。

  ContainsKey方法:确定Dictionary<,>中移除带有指定键的元素。

  Remove方法:从Dictionary<,>移除带有指定键的元素。

3. Queue<T>

  Queue泛型类表示对象的先进先出集合。

  常用方法如下:

  Enqueue方法:将指定元素插入列尾。

  Dequeue方法:队列首元素出列。

4. Stack<T>

  Stack泛型类表示同一任意类型的实例的大小可变的后进先出(LIFO)集合。

  常用方法如下:

  Push方法:将指定元素插入栈项。

  Pop方法:将栈项元素弹出。

5. SortedList<Tkey,Tvalue>

  SortedList泛型类表示键/值对的集合,这些键/值对基于关联的IComparer实现按照键进行排序。

  常用方法如下:

  Add方法:将带有指定键和值的元素添加到SortedList<,>中。

  TryGetValue方法:获取与指定的键相关联的值。

  ContainsKey方法:确定SortedList<,>中是否包含指定的键。

  Remove方法:从SortedList<,>中移除带有指定键的元素。

 

例5:现有一个活期存款账户类Account,为其提供处理业务的Customers类有一个方法CreateAccount(账户名,开户金额),试使用SortedList<,>创建泛型对象,并判断是否存在账户“张三”,若不存在,则创建账户;若存在,则为其追加存款。

主要代码如下所示:

代码
1 using System;
2 using System.IO;
3 using System.Collections.Generic;
4 namespace GenricExample
5 {
6 public class Account
7 {
8 private string accountName;
9 private int accountvalue;
10 public string AccountName
11 {
12 get
13 {
14 return accountName;
15 }
16 set
17 {
18 accountName=value;
19 }
20 }
21 public int AccountValue
22 {
23 get
24 {
25 return accountvalue;
26 }
27 set
28 {
29 accountvalue=value;
30 }
31 }
32 }
33 public class Customers
34 {
35 public void CreateAccount(string name,int value1)
36 {
37 Account acc=new Account();
38 acc.AccountName=name;
39 acc.AccountValue=value1;
40 }
41 }
42 class Porgram
43 {
44 static void Main(string[] args)
45 {
46 SortedList<string,Account> accounts=new SortedList<string,Account>();
47 Customers customs=new Customers();
48 if(accounts.ContainsKey("aa")==false)
49 {
50 //如果无此账户,创建账户,并将存款作为开户金额
51 Account account=new Account();
52 customs.CreateAccount("张三",1000);
53 accounts.Add("张三",account);
54 }
55 else
56 {
57 //如果有此账户,在现有账户上追加存款
58 Account account=accounts["张三"];
59 //account追加存款操作
60 }
61 }
62 }
63 }
64

 

 

posted on 2010-07-15 16:29  ZEKELOVE  阅读(535)  评论(2编辑  收藏  举报