扩展方法
在很多时候我们需要编写各种各样的帮助类,因为官方提供的再全面,也会有未包含到的地方,这时一个静态的帮助类就可以帮我们解决问题
举一个不是很恰当的例子,假如要对一个字符串进行验证其内容不为null并且等于admin但是很多地方都要调用,按照封装思想要封装成一个方法,看起来可能是下面这样子的
这并没有任何问题,代码也是比较简单,但是很难会有一种亲近感,因为StringiHelper.ValidArg这样的调用存在。比如这个验证应该是官方应该考虑到的,但是他们忽略了,编写这样一个扩展后会有很深的侵入感。
使用扩展方法,可以让方法假裝是字符串类型的自帶方法。像下面这样
与之前相比 ,我们更改了什么呢?在ValidArg方法的参数里加了一个this关键词,调用的时候直接str.ValidArg就可以了,这看起来很酷,也很神奇,看起来就像是string提供的原生方法一样!但事实是这样么,并不是,編譯器告訴了我们,它是扩展方法
编译器怎么会知道呢?调用的背后又做了什么呢? 其实没有想象的那么复杂,编译器查找时会优先查找实例方法也就是当前实例类型所在的命名空间进行扫描,如果没有实例方法那么就会去查找当前using的命名空间下和当前空间下所有的扩展方法,如果知道是扩展方法呢?请看下图
反编译后看到了有一个System.Runtime.CompilerServices.ExtensionAttribute的特性,也就是编译器会扫描所有加了ExtensionAttribute特性的方法当做扩展方法
而调用呢,最后还是使用了StringHelper.ValidArg这样的调用方式,
下面需要说一下扩展方法的使用和其限制,声明扩展方法需要遵守以下規則
- 它必须在一个非嵌套、非泛型的静态类中
- 方法至少有一个参数
- 第一个参数必须使用this关键词做为前缀
- 第一个参数不可以有任何其他的修改符
- 第一个参数的类型不可以是指针类型
有了扩展方法,我们可以对使用的第三方类库进行扩展,使其更加的强大!而且使用起来非常自然。管理扩展方法是一个经验之谈,最有效的就是使用命名空间进行管理。比如枚举,命名空间可以使用EnumExtension。