快速业务通道

C#教程:声明和调用扩展方法

作者 佚名技术 来源 NET编程 浏览 发布时间 2012-03-13

声明扩展方法

我们并不能将任何的方法都作为扩展方法——扩展方法必须要有以下的一些特性:

  • 它必须是被包含在一个非嵌套的, 非泛型的静态类当中(因此必须是静态方法)
  • 必须至少拥有一个参数
  • 第一个参数必须是由this关键字开头
  • 第一个参数不能有其他的修饰符, 例如out / ref
  • 第一个参数类型不能是一个指针类型

扩展方法本身可以是泛型的, 可以有返回值, 除了第一个参数外, 也可以包含ref / out参数, 可以作为partial类的一部分, 可以在迭代块当中来实现, 可以使用nullable类型——任何语法, 只要遵循了上述的约束.

我们把方法的第一个参数类型叫做extended type(被扩展的类型). 这并不是一个官方术语, 不过是一个有用的简短表达方式.

上面的列表不仅仅提供了所有的限制, 同时也表明了将静态方法变为扩展方法你需要做的步骤——加上this关键字. 以下的代码将我们之前的例子改造为扩展方法:

   1: public static class StreamUtil

 

   2: {

 

   3: const int BufferSize = 8192;

 

   4: public static void CopyTo(this Stream input,

 

   5: 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(this Stream input)

 

  15: {

 

  16: using (MemoryStream tempStream = new MemoryStream())

 

  17: {

 

  18: CopyTo(input, tempStream);

 

  19: return tempStream.ToArray();

 

  20: }

 

  21: }

 

  22: }

相比之前的例子, 我紧紧增加了两个this修饰符, 同时将方法名称从Copy改为CopyTo. 虽然现在在ReadFully当中看起来有点奇怪, 不过之后我们会看到这个改动会让我们的调用代码看起来更加自然.

调用扩展方法

简单来说, 改造实例代码来使用StreamUtil和改造该工具类一样简单. 这次, 我们不是要增加什么代码, 相反, 我们要去掉一些代码. 下面的代码使用我们提过的新的”语法”来调用CopyTo. 我说”新”实际上它根本就不新——因为它和我们一直使用的调用实例方法的语法一模一样.

   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:     responseStream.CopyTo(output);
   7: }

在上面的代码中, 至少它看起来像是我们让reponse流来完成copying的操作. 实际上幕后依然是StreamUtil在完成实际的工作, 但代码读起来更加自然了. 编译器在背后实际上仅仅是将CopyTo的调用转到了对StreamUtil.CopyTo的调用, 并传递responseStream作为方法的第一个参数.

你可能会注意并没有什么特别的东西指示我们到底是正在调用Stream的扩展方法还是常规的实例方法. 如果使用VS2008, 当你把鼠标移到一个方法调用上面的时候, 如果它是一个扩展方法, 那么将会出现一个明显的提示. 另外智能提示也会帮你指出哪些方法是扩展方法, 一个向下的箭头图标会出现在扩展方法前. 当然我们并不需要仔细到观察每一个方法来了解它是不是扩展方法, 因为多数情况下, 我们并不关心我们正在调用的到底是一个扩展方法还是一个实例方法.

在我们调用代码中, 还有一件可能会让人感到奇怪的事情, 那就是——StreamUtil根本就没有不提到! 编译器是怎么知道我们是要使用扩展方法的呢? 待续!

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号