当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > C#教程:声明和调用扩展方法

ASP.NET
asp.net Execl的添加,更新操作实现代码
asp.net 生成曲线图实现代码
从外部的js文件中获取ASPX页面的控件ClientID
asp.net 因为数据库正在使用的解决方法
asp.net Repeater 自递增
asp.net 实现防迅雷等下载工具盗链
ASP.NET封装的SQL数据库访问类
asp.net 通过指定IP地址得到当前的网络上的主机的域名
aspx 服务器架设问题解决
ASP.NET Session使用详解
Asp.net 5种页面转向方法
ASP.NET 用户多次登录的解决方法
ASP.NET下母版页和内容页中的事件发生顺序整理
asp.net 程序性能优化的七个方面 (c#(或vb.net)程序改进)
从客户端检测到有潜在危险的Request.Form值的asp.net代码
asp.net CommunityServer中的wwwStatus
在应用程序级别之外使用注册为allowDefinition=''MachineToApplication''的节是错误的
.net开发人员常犯的错误分析小结
ASP.net Substitution 页面缓存而部分不缓存的实现方法
asp.net 生成静态时的过滤viewstate的实现方法

ASP.NET 中的 C#教程:声明和调用扩展方法


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-28   浏览: 83 ::
收藏到网摘: n/a

声明扩展方法

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

  • 它必须是被包含在一个非嵌套的, 非泛型的静态类当中(因此必须是静态方法)
  • 必须至少拥有一个参数
  • 第一个参数必须是由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根本就没有不提到! 编译器是怎么知道我们是要使用扩展方法的呢? 待续!