您的位置:首页 > 其它

DotNet 3.0+ 新特性学习 之 扩展方法(Extension Method)

2009-09-23 14:07 281 查看

定义:


扩展方法允许对现存已编译的类型(例如 类,结构,接口)在不需要直接更新的情况下进行方法的扩展。

理解:

1) 扩展方法是对已编译类型的扩展。何为已编译类型? 说通俗点就是已经编译好的DLL或者exe。

2) 扩展方法不需要直接更新已编译类型。一般来说,一个已编译好的DLL,你是不知道它的具体实现的,只是在引用它以后,能知道它的public方法 (用Reflector查看代码除外)。当你需要针对某个已引用的DLL在自己的项目中进行扩展,怎么办。扩展方法就是解决这类问题的。

3) 扩展方法是对方法的扩展。换而言之,它不是对已编译类型的扩展。通俗点就是给已编译的类型增加一些方法。

4) 扩展方法不仅可以给某个类增加方法,还可以给结构,接口增加方法。有人可能觉得我给一个类增加方法的话可以使用继承。可以,没有问题。但是如果遇到seal ed class怎么办呢?

好了,啰嗦了一堆,大家肯定等急了吧。赶快来看咋用的吧。

实现

1. 扩展方法 ---

比如,我们需要给string类型加一个扩展方法,用来将string转化成int 数组。嘻嘻,熟悉string的同学们都知道,string本身并没有一个方法来直接转化成一个数组。 好了,开工了,请看下面的代码:

namespace ExtensionMethod

{

public static class ExtensionForClass

{

public static int[] ToIntArray(this string str)

{

// To do

}

}

}

铛铛铛铛~~ 神奇的事情发生了,当你在你的项目中引用ExtensionMethod 命名空间,在一个string变量后面点“.”,你就会发现一个ToIntArray()的方法。见下图

看见了吧。好神奇闹~~~.在此时,我们默认的数组分隔符是“,”,如果分隔符不定,那么我们可以重载此扩展方法,如下

namespace ExtensionMethod

{

public static class ExtensionForClass

{

public static int[] ToIntArray(this string str)

{

// To do

return default(int[]);

}

/// <summary>

/// Overload extension method ToIntArray

/// </summary>

/// <param name="str">source string</param>

/// <param name="separator">Separator</param>

/// <returns>Int Array</returns>

public static int[] ToIntArray(this string str, char separator)

{

// To do

return default(int[]);

}

}

}

恩, 搜噶,这样,我们就可以看到该方法的2个重载了,如下图

扩展方法 --- 结构

结构,结构??恩~~.net类库里现成的结构是啥呢?哦,对了,DateTime (别说你到现在还以为它是一个类哈)。比如说,有些数据库设计来说,把DateTime存成一个int的数,这样,在查找的时候,效率会很高,当然了,比较int要比比较DateTime要快呢。那么,我们在前台代码处理的时候,给DateTime加一个扩展方法,让它直接转化成Int。不多说废话,看下面代码

namespace ExtensionMethod

{

public static class ExtentionForStruct

{

public static int ToInt(this DateTime dateTime)

{

// To do;

}

}

}

奇迹再次发生,如下图:

瞧见了吗?嘿嘿。

扩展方法 --- 接口

扩展接口?这是个令人深思的话题,先不说为啥,先看代码

namespace ExtensionMethod

{

public interface ICount

{

int Add(int x, int y);

}

public static class ExtensionInterface

{

public static int Subtract(this ICount count, int x, int y)

{

return x - y;

}

}

}

看出问题了吗?啥?没有。哈哈,我第一次也没有看出来。大家想想,接口的一个特性是啥?就是接口并不自己实现方法,必须由实现该接口的类来实现方法,对不啦?但是,此时,对接口的扩展方法,已经实现了Subtract方法。这就对接口的本质造成了破坏。可能有人会问,那不能写成这样?

public static int Subtract(this ICount count, int x, int y);

呵呵,have a try,看看会出现啥?(读者作业)。

怎么用呢?

namespace ExtensionMethod

{

class Program

{

static void Main(string[] args)

{

ICount count = new MyCount();

count.Subtract(5, 4);

}

}

class MyCount : ICount

{

public int Add(int x, int y)

{

return x + y;

}

}

}

这回看明白了,由于只是对接口的一个方法的扩展,且已经有了实现,所以,对实现接口的类就不会强迫其实现”Substract”方法。 但是,在使用接口的时候,Substract 却切切实实的在哪呢。

小贴士:

个人还是建议少用对接口的扩展方法,因为这毕竟破坏了面向对象的本质,也不可能对实现接口的类进行行为上的限制。

约束

1) 扩展方法必须放在static 类里面,且本身也是static的。

2) 扩展方法的第一参数必须是你要扩展的类型,this + 类型 + 参数名。

3) 每一个扩展方法之可以被内存中正确的实例调用,或者通过其所处的静态类调用。

4) 扩展方法不可以直接访问扩展类型的成员。

比如

public class Car

{

public int Speed { get; set; }

public void SpeedUp() { Speed++; }

}

public static class CarExtension

{

public static void SpeedDown(this Car car)

{

// It's wrong

// Speed--;

// It's right

car.Speed--;

}

}

扩展方法的本质

先看如下代码

class Program

{

static void Main(string[] args)

{

ICount count = new MyCount();

// They are same

count.Subtract(5, 4);

ExtensionInterface.Subtract(count, 5, 4);

}

}

哈哈,被骗了吧,其实是微软玩的一个障眼法。其实它就是 “ExtensionInterface.Subtract(count, 5, 4);”。

个人建议

呼,总算写完了,个人一点点建议哈

1) 扩展方法的命名要遵循所扩展类型的其他方法的命名习惯。

2) 相关类型的扩展方法放到相关类型的命名空间下,在加一个Extension。比如关于System.Data的扩展方法的命名空间就是System.Data.Extension。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐