扩展方法详解

简介:

一、基础

扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。扩展方法是一种特殊的静态方法,调用扩展方法与调用在类型中实际定义的方法之间没有明显的差异。扩展方法是可以通过使用实例方法语法调用的静态方法。效果上,使得附加的方法扩展已存在类型和构造类型成为可能。他可以对现有类功能进行扩充,从而使该类型的实例具有更多的方法。扩展方法有助于把今天动态语言中流行的对快速录入支持的灵活性,与强类型语言之性能和编译时验证融合起来。这里先举一个msdn中的例子:
下面的示例演示为 System.String 类定义的一个扩展方法。假设我要分析一个字符串,希望得到字符串中单词的个数,一般情况下我们可能使用一个统计的函数来解决这个问题

 

ContractedBlock.gif 代码

 

 

 

但这样用起来感觉上可能会很别扭,这个WordCount方法如果就是字符串类中的一个方法多好,像所有字符串的实例方法一样用。这里我们引出扩展方法来解决这个问题。

 

ContractedBlock.gif 代码

 

 

注意,上面的静态方法在第一个类型是string的参数变量前有个“this”关键词,这告诉编译器,这个特定的扩展方法应该添加到类型为“string”的对象中去。
使用 using 指令将 WordCount 扩展方法放入范围中:
using ExtensionMethods;

string  s  =   " Hello Extension Methods " ;
int  i  =  s.WordCount();

 

二、应用场景

1、扩展类库中已经存在的类

比方说我们是无法改变系统已经存在的类的,就像上例中我们无法在string类中添加WordCount方法,但我又希望在使用时直接使用

这篇文章c#扩展方法奇思妙用中也有很多例子,大家可以参考一下

2、多个类实现接口时有些方法实现方式相同,所以不希望每个实现类中重新实现一遍

假如系统中用户接口需要两个类实现,希望IUser接口声明的实体都有检测Email的方法IsUniqueEmail,而实际上这个方法在所有实现类中的实现逻辑都是一样的,而我们如果把这个方法添加到IUser中,那么两个类就要都实现一遍IsUniqueEmail的逻辑。中间加一层继承关系也可以解决问题,这种方式会增加维护成本,这时我们可以使用扩展方法

如下图:

2010052417482279.jpg

代码模拟如下:

 

ContractedBlock.gif 代码

 

ContractedBlock.gif 代码

 

 
 
static void Main( string [] args)
{
IUser user
= new UserLinqToOracle();
Console.WriteLine(user.IsUniqueEmail(
"" ));
}

 

三、扩展方法要点 
1、扩展方法的本质为将实例方法调用在编译期改变为静态类中的静态方法调用。事实上,它确实拥有静态方法所具有的所有功能。 
2、通常,您更多时候是调用扩展方法而不是实现您自己的扩展方法。由于扩展方法是使用实例方法语法调用的,因此不需要任何特殊知识即可从客户端代码中使用它们。若要为特定类型启用扩展方法,只需为在其中定义这些方法的命名空间添加 using 指令。
3、扩展方法的优先级:现有实例方法优先级最高,其次为最近的namespace下的静态类的静态方法,最后为较远的namespace下的静态类的静态方法。(与接口或类方法具有相同名称和签名的扩展方法永远不会被调用 )

ContractedBlock.gif 代码

 

 

结果为“来源于实例方法:lfm”

 

ContractedBlock.gif 代码

 

 

结果为:“来源于较近的扩展方法:lfm”

4、在接口上扩展的方法,如果用接口声明时会优先使用基于接口的扩展方法

 

ContractedBlock.gif 代码

 

 

结果为:来源于扩展方法:lfm@126.com

但如果接口中又被添加了相应的方法,将优先使用实例方法

 

ContractedBlock.gif 代码

 

 

结果为:来源于实例方法:lfm@126.com
5、在代码中,可以使用实例方法语法调用该扩展方法。但是,编译器生成的中间语言 (IL) 会将代码转换为对静态方法的调用。因此,并未真正违反封装原则。实际上,扩展方法无法访问它们所扩展的类型中的私有变量。


四、扩展方法通用准则 
1、通常,建议您只在不得已的情况下才实现扩展方法,并谨慎地实现。只要有可能,必须扩展现有类型的客户端代码都应该通过创建从现有类型派生的新类型来达到这一目的。
2、在使用扩展方法来扩展您无法更改其源代码的类型时,您需要承受该类型实现中的更改会导致扩展方法失效的风险。
3、如果您确实为给定类型实现了扩展方法,请记住以下两点:
     如果扩展方法与该类型中定义的方法具有相同的签名,则扩展方法永远不会被调用。
     扩展方法在命名空间级别被放入范围中。例如,如果您在同一个名为 Extensions 的命名空间中具有多个包含扩展方法的静态类,则这些扩展方法将全部由 using Extensions; 指令放入范围中。

本文转自 你听海是不是在笑 博客园博客,原文链接:http://www.cnblogs.com/nuaalfm/archive/2010/05/24/1742951.html  ,如需转载请自行联系原作者


相关文章
|
7月前
|
编译器 C#
c# 自定义扩展方法
c# 自定义扩展方法
|
C#
c#中的扩展方法
c#中的扩展方法
64 0
EntityFramework——委托与Lambda表达式
EntityFramework——委托与Lambda表达式
109 0
EntityFramework——委托与Lambda表达式
|
开发框架 .NET C#
面向对象——扩展方法
面向对象——扩展方法
120 0
|
C# .NET 开发框架