有关泛型的用法

  泛型(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         常见的泛型集合类及对应的非泛型集合类

2010071516221069.jpg

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<,>创建泛型对象,并判断是否存在账户“张三”,若不存在,则创建账户;若存在,则为其追加存款。

主要代码如下所示:

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
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

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值