CLR via C#(09)-扩展方法
对于一些现成的类,如果我们想添加一些新的方法来完善功能,但是不想改变已有的封装,也不想使用派生类,那么该怎么办呢?这里我们可以使用扩展方法。
一见钟情--初识扩展
扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。
我们首先来看个例子,有个直观的认识。一个现有的类User:
public class User
{
string _name;
public User(string Name)
{
_name = Name;
}
public string Name
{
get { return _name; }
set { this._name = value; }
}
}
现在我们想要增加一个方法来显示user信息,又不想修改User类。使用扩展方法

扩展方法是一种比较特殊的使用,我们可以定义静态方法,然后在目标类型中以实例方法的语法进行调用。有了上面的定义后,当使用User实例时,会产生相应的智能感知,而且会提示是扩展方法。

调用结果
User user = null;//实例为null
user.DisplayName();
user = new User("小静");//实例不为Null
user.DisplayName();
Console.Read();
查看ILDASM.exe,我们看到定义扩展方法后,Extension类会添加一个ExtensionAttribute标记。

了解扩展
怎样定义扩展方法?
- 定义一个静态类,名称不限;
- 定义静态方法,第一个参数类型为要扩展的目标类型;为了表明是扩展方法,还要给第一个参数添加this关键字。
编译过程识别顺序?
在上面的例子中,调用语句为user.DisplayName();,那么编译器的检查过程:
- 首先检查变量类型User及其基类是否定义了DisplayName()实例方法,如果存在则会生成调用该方法的IL代码;
- 如果不存在,则会继续检查静态类中是否存在一个名为DisplayName、第一个参数为User而且带有this关键字的静态方法,如果存在就会生成相应的IL代码。
- 如果仍然不存在,则会产生编译错误。
正果守则--扩展规则
- 扩展方法必须在非泛型静态类中声明,类名无限制,例如Extension类的名字可以任意修改后,都能正常调用扩展方法。扩展方法至少有一个参数,且第一个参数是目标扩展类型且用this关键字标识。
- 扩展方法所在的静态类不能嵌套在另外一个类中。像下面这样定义会产生编译错误。


- 扩展方法可以在不同的静态类中定义,所以不同的静态类中可能出现同名的扩展方法,编译器纠结了不知道该如何调用,只好产生编译错误。例如

此时,我们不能再用实例方法的语法来调用了,只能用静态方法语法调用。
user = new User("小静");//实例不为Null
Extension.DisplayName(user);
Extension1.DisplayName(user);
- 派生类也继承了扩展方法, 例如我们定义派生类Student:
public class Student:User{}
它的智能感知,也包含了User类的扩展方法。

所以在定义扩展方法时要比较注意,不能过多使用。基类中使用过多的扩展方法后,也许会使派生类中产生一些多余的智能感知。
- 版本问题。如果某一天向目标扩展类定义了同名的方法DisplayName后,调用时就会覆盖之前的扩展方法,改变原先程序的行为。所以扩展方法要慎重使用。


- 扩展方法和实例方法虽然语法看上去一样,但它俩有一个重要的区别,看下面这个调用。
User user = null;//实例为null
user.DisplayName();
实例方法调用时,对象不能为null,会产生运行时错误。
扩展方法世界上是调用静态方法,所以调用它的实例对象可以为Null。
- 扩展接口?
除了为类型扩展方法外,还可以为接口定义扩展方法。例如

调用过程:
new[] { "AA", "BBB", "CCCC" }.ShowItems();
"Cathy".ShowItems();
Console.Read();
结局才是开始
这篇对扩展方法的介绍到这里算是happy ending了吧。其实说起这个话题,鹤冲天 兄台的研究就深入多了。我就当是抛砖引玉了,大家有兴趣的话学习他的系列c# 扩展方法奇思妙用
扩展方法好资料:
- MSDN: 扩展方法(C# 编程指南)
http://msdn.microsoft.com/zh-cn/library/bb383977.aspx
- 博客园: 鹤冲天 c# 扩展方法奇思妙用
http://www.cnblogs.com/ldp615/archive/2009/08/07/1541404.html
CLR via C#(09)-扩展方法的更多相关文章
- C#的扩展方法解析
		在使用面向对象的语言进行项目开发的过程中,较多的会使用到“继承”的特性,但是并非所有的场景都适合使用“继承”特性,在设计模式的一些基本原则中也有较多的提到. 继承的有关特性的使用所带来的问题:对象的继 ... 
- 【开源】OSharp框架解说系列(3):扩展方法
		OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ... 
- 《精通C#》自定义类型转化-扩展方法-匿名类型-指针类型(11.3-11.6)
		1.类型转化在C#中有很多,常用的是int类型转string等,这些都有微软给我们定义好的,我们需要的时候直接调用就是了,这是值类型中的转化,有时候我们还会需要类类型(包括结构struct)的转化,还 ... 
- 爱上MVC~为CheckBoxFor和RadioButtonFor加个扩展方法吧(希望MVC5把这方法收纳——呵呵)
		回到目录 说在前 我都是喜欢把问题复杂化,还有总是喜欢把问题简单化,偷懒化,这也需就是一个程序员的追求吧,呵呵. 我不太喜欢重复的东西,当你看到页面上有一个以上相同的代码时,那可以说,你的代码有重构的 ... 
- C#扫盲之:带你掌握C#的扩展方法、以及探讨扩展方法的本质、注意事项
		1.为什么需要扩展方法 .NET3.5给我们提供了扩展方法的概念,它的功能是在不修改要添加类型的原有结构时,允许你为类或结构添加新方法. 思考:那么究竟为什么需要扩展方法呢,为什么不直接修改原有类型呢 ... 
- c# 如果一个对象的值为null,那么它调用扩展方法时为甚么不报错
		如果一个对象的值为null,那么它调用扩展方法时会报错吗? Person p = null ; p.ExtendMethod(); 上述代码出现的情况不会报错,刚开始遇到这种情况时很纳闷,就去问了大牛 ... 
- c#写扩展方法
		学习MVC时,学会了写扩展方法,用起来很方便. 01 using System; 02 using System.Collections.Generic; 03 using System.Linq; ... 
- C# 知识回顾 - 扩展方法解析
		在使用面向对象的语言进行项目开发的过程中,较多的会使用到“继承”的特性,但是并非所有的场景都适合使用“继承”特性,在设计模式的一些基本原则中也有较多的提到. 继承的有关特性的使用所带来的问题:对象的继 ... 
- 【转载】C#扫盲之:带你掌握C#的扩展方法、以及探讨扩展方法的本质、注意事项
		1.为什么需要扩展方法 .NET3.5给我们提供了扩展方法的概念,它的功能是在不修改要添加类型的原有结构时,允许你为类或结构添加新方法. 思考:那么究竟为什么需要扩展方法呢,为什么不直接修改原有类型呢 ... 
随机推荐
- BZOJ2051——A Problem For Fun
			0.题意:给出一个N个结点的树,每条边有一个正整数权值,定义两个结点的距离为连接这两个结点路径上边权的和.对于每个结点i,它到其他N-1个结点都有一个距离,将这些距离从小到大排序,输出第K个距离. 1 ... 
- Android坐标系统
			1 背景 去年有很多人私信告诉我让说说自定义控件,其实通观网络上的很多博客都在讲各种自定义控件,但是大多数都是授之以鱼,却很少有较为系统性授之于渔的文章,同时由于自己也迟迟没有时间规划这一系列文章, ... 
- PyQt4 QListview控件使用方法
			1.往QListView控件内写入数据 strlist=QStringList()strlist.append('hello')strm=QStringListModel(strlist)self.u ... 
- MySQL 临时表的使用
			-- step 1.创建临时表,命名为item_orders create temporary table item_orders ( item_id int, orderList ) ) -- st ... 
- iOS学习之UINavigationController详解与使用(一)添加UIBarButtonItem
			http://blog.csdn.net/totogo2010/article/details/7681879 1.UINavigationController导航控制器如何使用 UINavigati ... 
- Xcode 6 正式版如何创建一个Empty Application
			Xcode 6 正式版里面没有Empty Application这个模板,这对于习惯了纯代码编写UI界面的程序员来说很不习惯. 有网友给出了一个解决方法是,把Xcode 6 beta版里面的模板复制过 ... 
- MQTT V3.1----publish解读
			客户端/服务器的发布消息行为,与PUBLISH相关的消息类型: PUBLISH 客户端发布消息经由服务器分发到所有对应的订阅者那里.一个订阅者可以订阅若干个主题(Topic name),但一个PUBL ... 
- C++中string,wstring,CString的基本概念和用法
			一.概念 string和CString均是字符串模板类,string为标准模板类(STL)定义的字符串类,已经纳入C++标准之中.wstring是操作宽字符串的类.C++标准程序库对于string的设 ... 
- OGNL表达式
			一.什么是OGNL,有什么特点? OGNL(Object-Graph Navigation Language),大概可以理解为:对象图形化导航语言.是一种可以方便地操作对象属性的开源表达式语言 ... 
- UrlEncoder url编码
			public static string PercentEncode(string s) { var bytes = Encoding.UTF8.GetBytes( ... 
 
			
		
