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

ASP.NET
Asp.net 时间操作基类(支持短日期,长日期,时间差)
asp.net 获取机器硬件信息(cpu频率、磁盘可用空间、内存容量等)
asp.net 数据库备份还原(sqlserver+access)
Asp.Net 数据操作类(附通用数据基类)
Asp.net 弹出对话框基类(输出alet警告框)
Asp.net 文件上传类(取得文件后缀名,保存文件,加入文字水印)
Asp.net Socket客户端(远程发送和接收数据)
Asp.net 字符串操作基类(安全,替换,分解等)
Asp.Net数据输出到EXCEL表格中
asp.net Gridview里添加汇总行
asp.net UpdatePanel的简单用法
asp.net ajaxControlToolkit FilteredTextBoxExtender的简单用法
this connector is disabled错误的解决方法
sql事务应用积累
asp.net Page.Controls对象(找到所有服务器控件)
在asp.NET中字符串替换的五种方法
ASP.NET缓存方法分析和实践示例代码
asp.net 在DNN模块开发中遇到的resx怪问题
ASP.NET State service状态服务的问题解决方法
asp.net 结合mysql存储过程进行分页代码

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


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