彻底剖析C# 2.0泛型类的创建和使用-阿里云开发者社区

开发者社区> 技术小甜> 正文

彻底剖析C# 2.0泛型类的创建和使用

简介:
+关注继续查看
"一次编码,多次使用",这就是引入泛型的根源。在以前的C++中称为模板,C#泛型通过算法和数据结构支持独立编码。例如,泛型列表意味着,你不必再重写一个强类型集合。在本文中,作者将向你展示定义和使用泛型是多么容易的事情-请注意,长期以来泛型一直被认为是最高级和最困难的术语。

  一、 简介

  泛型现在在任何一种语言中都被认为是一个高级的强有力的术语。当我在C++中第一次接触模板时,我对之有些疑惑。之后,我读了Bjarne Stroustrop的《The Design and Evolution of C++》,才发现模板的使用就象C中的宏和用之来取代的简单串替换模板一样容易。其实,模板和泛型是相同的东西-尽管它们的实现稍微不同。

  C#泛型支持在使用点处才定义算法及其数据类型。在C#的一些早期版本中,我们可以证明没有泛型也可以工作,因为每种类型都是派生于一个公共基类型- object。这意味着程序员可以基于object类型定义一个栈类并且把一切东西放到该栈上(因为一切都派生于object)。然而,一个object 栈意味着,Customer对象,Integer对象以及假想的对象都能被放置到同一个栈的实例上。结果是,开发者要子类化数据类型来把数据类型绑定到他们要与之交互的东西上去。例如,在编写定制的商业对象时,我们就建议定义派生于System.Collections.CollectionBase的强类型集合。原因很简单:基于object定义一切被认为是弱类型定义。

  业界的高手们在数十年前就确信强类型优于弱类型,所以.net最终支持强类型,这看上去是很自然的事情。强类型算法当然建议类型化参数-这正是我们在泛型中所用的东西。

  十几年来,我们一直在使用字母T作为类型化参数的名字。这样,在任何泛型类使用者所提供的数据类型的地方,你都能够找到T。使用泛型的关键仅仅是提供这个T。定义泛型的关键在于实现一个方法或类,并且用特定数据类型来替换掉T。

  C#中的泛型支持另外一些提炼。例如,一个方法或类可以有多个参数化的类型并且C#泛型还支持WHERE约束-它用来具体要求类型化参数的类型。例如,如果一个泛型类型必须实现接口IDisposable,那么C#泛型是支持实现这一限制的。在文章的最后我们还要看一下约束问题。
闲话少说,让我们言归正传。

  二、 使用泛型集合

  有些人问我"面向对象编程(OOP)的承诺在哪里?",我的回答是应该从两个方面来看OOP:你所使用的OOP和你创建的OOP。如果我们简单地看一下如果没有如例如Microsoft的.NET,Borland的VCL,以及所有的第三方组件这样的OO框架,那么很多高级的应用程序几乎就无法创建。所以,我们可以说OOP已经实现了它的承诺。不错,生产好的OOP代码是困难的并且可能是极具挫败性的;但是记住,你不必须一定要通过OOP来实现你的目标。因此,下面首先让我们看一下泛型的使用。

  当你用 Visual Studio或C# Express等快速开发工具创建工程时,你会看到对于System.Collections.Generic命名空间的参考引用。在这个命名空间中,存在若干泛型数据结构-它们都支持类型化的集合,散列,队列,栈,字典以及链表等。为了使用这些强有力的数据结构,你所要做的仅是提供数据类型。

  列表1显示出我们定义一个强类型集合的Customer对象是很容易的。

  列表1 这个控制台应用程序包含一个Customer类和一个基于List<T>的强类型集合Customers。

using System;
using System.Collections.Generic;
using System.Text;
namespace Generics{
 class Program{
  static void Main(string[] args){
   List<Customer> customers = new List<Customer>();
   customers.Add(new Customer("Motown-Jobs"));
   customers.Add(new Customer("Fatman's"));
   foreach (Customer c in customers)
   Console.WriteLine(c.CustomerName);
   Console.ReadLine();
  }
 }
 public class Customer{
  private string customerName = "";
  public string CustomerName{
   get { return customerName; }
   set { customerName = value; }
  }
  public Customer(string customerName){
   this.customerName = customerName;
  }
 }
}

  注意,我们有一个强类型集合-List<Customer>-对这个集合类本身来说不需要写一句代码。如果我们想要扩展列表customer,我们可以通过从List<Customer>继承而派生一个新类。
三、 实现一个泛型类

  一种合理的实现某种新功能的方法是在原有的事物上进一步构建。我们已经了解强类型集合,并知道一种不错的用来构建泛型类的技术是使用一个特定类并删除数据类型。也就是说,让我们定义一个强类型集合CustomerList,并且来看一下它要把什么东西转化成一个泛型类。

  列表2定义了一个类CustomerList。后面的部分把CustomerList转化成List<T>。

  列表2定义类CustomerList:

using System;
using System.Collections;
using System.Text;
namespace Generics{
 public class CustomerList : CollectionBase{
  public CustomerList() { }
  public Customer this[int index]{
   get { return (Customer)List[index]; }
   set { List[index] = value; }
  }
  public int Add(Customer value)
  {return List.Add(value);}
 }
}

  四、 定义类头

  如果我们定义一个泛型类,我们需要把类头转化成一个泛型类。所有我们需要做的是命名参数并且把类名改成某种泛型。List<T>只有一个参数T,并且因为我们在以一种向后兼容的方式工作,所以我们知道类名是List。列表3显示出列表2中类的新类头。

  列表3 一个泛型类头显示出参数化的参数T。

using System;
using System.Collections;
using System.Text;
namespace Generics{
public class List<T> : CollectionBase {}

  五、 实现泛型字段

  如果我们需要把任何字段转换成泛型字段,我们将只需简单地把它们的类型改变成T(或该字段所描述的任何参数)。泛型List不需要任何字段,但是假定存在一个私有的整型字段叫foo-我们将把它泛型化。我们将如下重新定义它:

private T foo;

  当参数T被填充到类中时,List T也将因foo被填充。

  六、 定义泛型方法

  接下来,我们为所需要的参数化类型定义其它一些特性。这包括属性,方法,和事件。在我们的实例中,在Customer出现的每一处,我们都用参数T替换它。完成后的泛型列表类显示于列表4中。

  列表4 一个基于System.Collections.CollectionBase的轻量级的参数化泛型列表类。

using System;
using System.Collections;
using System.Text;
namespace Generics{
 public class List<T> : CollectionBase {
  public List(){ }
  public T this[int index] {
   get { return (T)List[index]; }
   set { List[index] = value; }
  }
  public int Add(T value) {
   return List.Add(value);
  }
 }
}

  为了测试该定制列表,注释掉使用System.Collections.Generic命名空间一句并且把列表4中的List<T>使用在列表1的代码中;它将以同样的方式工作。

  全面地修改.net的List<T>是不必要的而且它也包含远比我们的示例多得多的特性;但是列表4显示出这种机制对于定义定制泛型类是多么容易。
七、 增加类型约束

  最后要讨论的是约束问题。约束被应用于类或其它特性上并且使用下面的语法:

Where T : constraint_type

  例如,任何我们想要通过using语句所使用的,如一个SqlDataReader,必须实现Idisposable接口。这是因为如下方式使用的using语句:

using(Form f = new Form()){...}

  就象一个 try..finally块一样工作-总是清除新创建的资源。其工作原理很简单,只需要CLR针对在该using语句中创建的对象发出一个到 IDisposable.Dispose的调用即可。例如,在上面这一句中,一个新的表单被创建,并且在using语句退出之前即调用 Form.Dispose。
要对一个泛型类施加以确保该类实现了接口IDisposable,我们将添加先行词where T:Idisposable。在列表4中的泛型列表上施加约束后,我们将重新修改列表4如下面的列表5所示。

  列表5 增加一个约束到泛型类以确保我们的List<T>中的所有的值T实现接口Idisposable。

using System;
using System.Collections;
using System.Text;
namespace Generics{
 public class List<T> : CollectionBase where t : IDisposable{
  public List(){ }
  public T this[int index]{
   get { return (T)List[index]; }
   set { List[index] = value; }
  }
  public int Add(T value){return List.Add(value);}
 }
}

  先行词where的值可以是类,接口,结构,实现一个无参的公共构造器或有一个特定的基类的类。详见有关帮助文档。

  八、 总结

  泛型的设计是用来减少你重复实现的代码的次数-只需改变数据类型即可。因为抽象数据结构,如队列,栈和列表皆是典型的数据结构,所以存在针对这些东西的泛型类完全可以理解。你可以从.net中派生大量的值-通过使用现有的泛型类,如在System.Collections.Generic命名空间中的那些。

  可以肯定,在一段相当长的时间里,泛型将会象模式和重构等革新一样对开发带来越来越大的价值,而且新的数据结构能被转换成可重用的如泛型等的代码元素。 















本文转自朱先忠老师51CTO博客,原文链接:http://blog.51cto.com/zhuxianzhong/59687 ,如需转载请自行联系原作者


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
JavaScript正则使用点滴
写在前面:关于“railroad diagrams”,摘抄自网络:http://202.207.0.245:9001/jisuanjifazhanshi/tuling/19.htm     我们目前所看到的许多语言的BNF实际上是EBNF,不过人们往往忽略掉这个E字。
577 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
4397 0
创建 floating IP - 每天5分钟玩转 OpenStack(106)
先复习一下前面我们讨论的知识。 当租户网络连接到 Neutron router,通常将 router 作为默认网关。当 router 接收到 instance 的数据包,并将其转发到外网时: 1. router 会修改包的源地址为自己的外网地址,这样确保数据包转发到外网,并能够从外网返回。
900 0
codeblocks创建和使用静态库(C语言)
静态库  (扩展名为 .a 或 .lib) 是包含函数的文件,用于在link阶段整合执行程序,动态链接库(扩展名  .dll)是不在link阶段整合进执行程序中的。 DLL文件在执行阶段动态调用 下面我们将用免费的开发工具CodeBocks开发静态库 创建静态库 启动Codeblocks并创建一个类型为 "Static Library" (File/New/Project/Static Library/Go)的项目。
943 0
+关注
6323
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载