网站主页   操作系统    网络工程    服务器    网页制作    数据库    程序开发    网络安全    办公软件   
讲座日期: 本周六下午1点30分 抢座
讲座地点: 北大青鸟马甸校区
主讲老师: 王老师 金牌讲师
讲座主题: 网络安全
讲座内容: 检测、防御、黑客信息,如何过滤不安全的网站,如何防御黑客的进攻。
订座电话: 010-82011432/33
  您当前位置:主页 > 网络学院 > 程序开发 > C++/C教程 >

C#教程:没有扩展方法的日子




没有扩展方法的日子

如果在开始使用C# 3之前你已经编写了很多的C# 2代码, 你应该看一下你的静态类——它们中的大多数都是可以被转换成扩展方法的候选. 这并不是说所有已经存在的静态类都适合, 但你可以透过下面的特征来认出它:

  • 你想增加成员到一个类型上
  • 你不需要增加任何的数据到类型实例上
  • 你不能改变类型本身, 因为它来自于其他人的代码

另一种情况你可能也想可以使用接口来代替具体类型, 然后添加一些有用的方法到接口上面, 并通过接口来调用也可以实现类似的要求. 一个好的例子就是IList<T>. 如果它能够对所有实现了IList的类型进行排序那应该会是非常美妙的事情, 然而这会要求所有的接口实现都要实现如何对它们自己排序, 这是非常可怕的. 当然从用户的角度来看还是相当不错的.

问题是IList<T>已经提供了一个完整的泛型排序例程, 但是我们却不能将完整的实现放在该接口中(接口不能有实现). 我们当然可以将其指定为抽象类, 这样就可以包含排序的实现了, 但.NET和C#只允许单继承, 这将会严重限制那些从它继承出去的类型. 扩展方法可以允许我们排序任何IList<T>的实现, 看起来就像是它本身就提供了这个功能一样.

接下来让我们来看一个例子, Stream类是.NET当中二进制通讯的基础, Stream本身是一个抽象类, .NET Framework包含有几个具体的实现类, 例如NetworkStream, FileStream, MemoryStream. 不幸的是, 有些个功能本该被包含在Stream当中, 然而实际上它们并没有.

最常见的缺失功能是读取一个流到内存当中并且保存为二进制数组的功能以及将一个流的内容拷贝到另外一个当中. 如果能将它们集中实现, 避免在不同的项目之间复制一些糟糕的实现无疑将会是是很不错的主意. 下面的代码提供了我们提到的这些额外的对Stream的功能要求.

   1: using System.IO;
   2: public static class StreamUtil
   3: {
   4:     const int BufferSize = 8192;
   5:     public static void Copy(Stream input,Stream output)
   6:     {
   7:         byte[] buffer = new byte[BufferSize];
   8:         int read;
   9:         while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
  10:         {
  11:             output.Write(buffer, 0, read);
  12:         }
  13:     }
  14:     public static byte[] ReadFully(Stream input)
  15:     {
  16:         using (MemoryStream tempStream = new MemoryStream())
  17:         {
  18:         Copy(input, tempStream);
  19:         return tempStream.ToArray();
  20:         }
  21:     }
  22: }

这个工具类本身并没有太多东西需要解读, 仅仅是为了方便之后引入扩展方法, 接下来看看我们如何使用这个工具类:

   1: WebRequest request = WebRequest.Create("http://manning.com");
   2: using (WebResponse response = request.GetResponse())
   3: using (Stream responseStream = response.GetResponseStream())
   4: using (FileStream output = File.Create("response.dat"))
   5: {
   6:     StreamUtil.Copy(responseStream, output);
   7: }

上面的代码已经是很简洁的了, StramUtil会自动循环接受流当中所有的数据, 其很好的完成了工作. 唯一的一点就是看起来不是那么面向对象, 我们更喜欢能够让响应的数据流拷贝自己到输出流当中, 就像MemeryStream自己的WriteTo方法一样. 这不是什么大问题, 仅仅是有一点丑陋.


上一篇:C#教程:声明和调用扩展方法  
下一篇:C#教程:编程方式构建表达式树
相关信息:

·虚拟文件系统 ·Oracle应用Linux开发C
·Linux 核心 ·计算机病毒的分类
·Unix(Linux)C编程问题精粹 ·指针与函数的关系
·内核模块的编译文件 ·如何检测Sniffer
·解析C语言中的sizeof ·用C语言小程序来解决大问题

Copyright © 2002-2015 版权所有
学校地址:北京市海淀区西三旗建材城中路29号北大青鸟
招生热线:010-82011433/32 京公网安备110102004704  京ICP备05043413号 京公网安备110102004704