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

ASP.NET
一个无刷新效果定时自动更新页面的例子
ASP.NET2.0的控件状态和视图状态探讨
用好ASP.NET 2.0的URL映射
详解:如何在.NET中访问MySQL数据库?
如何实现Asp与Asp.Net共享Session
利用.net的强大功能发送email
.NET中加密与解密QueryString的方法
Asp.net生成htm静态文件的两种途径
C#定时器的使用
从XML文件中读取数据绑定到DropDownList
ASP.NET 2.0 里输出文本格式流
用.net动态创建类的实例
.Net下的MSMQ的同步异步调用
ASP.NET 2.0实现防止同一用户同时登陆
asp.NET自定义服务器控件内部细节
组合.NET数据控件构建强大用户接口
用ASP.NET 2.0 FormView控件控制显示
菜鸟也学习ASP.NET如何读取数据库内容
教你简单方便获取Web设计的免费资源
专家详解:复杂表达式的执行步骤

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


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-28   浏览: 40 ::
收藏到网摘: 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根本就没有不提到! 编译器是怎么知道我们是要使用扩展方法的呢? 待续!