本文参考自唔愛吃蘋果的C#原始类型扩展方法—this参数修饰符,并在其基础上作了一些细节上的解释html
一、this做为参数关键字的做用框架
使用this关键字,能够向this关键字后面的类型添加扩展方法,而无需给其建立新的派生类型、从新编译或以其余的方式修改类型.ide
扩展方法是一种特殊的静态方法,但能够像实例方法那样调用。可是this关键字最主要的做用是对类型的重载方法的扩充,来知足自身的需求,由于有些类方法的重载方法可能不是很完善,而直接修改类型的条件不足(应为可能有些已经被编译成dll,有些测试.net框架的底层类),因此只能经过this关键字对其进行扩展,也就是完善类方法的重载方法。函数
说了这么多,可能你仍是不理解,如今有个需求:post
我想利用string.format拼接一个,异常字符串,具体内容是: ("parameter {0} cannot be empty",parameter),我知道使用string.format能很好地胜任,可是string.format静态方法我用不习惯,因此我想将它改造为string类的实例方法,直接经过"".实例方法来调用,最后的效果就是:"parameter {0} cannot be empty".实例方法名(parameter)测试
可是我不可能修改string类,来达到这个目地,由于string类是.Net Framework的底层类库,因此只能使用this关键字,来给其添加扩展方法,代码以下:this
public static class StringUtilities { public static string FormatWith(this string format,IFormatProvider provider,object org0) { return format.FormatWith(provider, new object[] { org0 }); } public static string FormatWith(this string format, IFormatProvider provider, object[] args) { return string.Format(provider,format,args); } }
ok,如今经过this关键字给string类添加了两个实例重载方法,可是须要注意,这里的类必须就静态类,扩展方法必须是静态方法,缘由以下:url
(1)、这里传入的须要扩展的string类型spa
不是静态变量而是成员变量.net
(2)、静态类的特色,若是一个静态类没有加构造函数,那么编译器会自动的给它加一个静态构造函数,静态构造函数是最先被调用的,只要有静态访问,那就先调用静态构造函数,接着调用非静态构造函数,并且静态类里面的成员在第一次被访问以后,就会被添加到全局环境中,后面的访问,将不会执行初始化操做,直接调用便可。并且静态类中不能有成员变量,this关键字是个列外
(3)、当类是静态类时,程序会在编译的时候,就将全部的静态成员编译到全局环境中,当类不是静态类的时候,只有当类中的静态成员被调用以后,才会被初始化到全局环境中,也就是说,代码以下:
public class StringUtilities { public static string FormatWith(this string format, IFormatProvider provider, object org0) { return format.FormatWith(provider, new object[] { org0 }); } }
这里的StringUtilities不是静态类,因此只要当StringUtilities的FormatWith在被初始化以后,他才会被初始化到全局环境中,下一次调用就不须要初始化了直接去全局环境中取,因此这个时候
这样是调不到FormatWith方法的,应为此时的FormatWith方法尚未被初始化,因此编译器会报错
,可是若是将StringUtilities改成静态类,那么编译器就会在编译完后,就将全部的静态成员初始化到全局环境中,这样上面出错的代码就没问题了,代码以下:
public static class StringUtilities { public static string FormatWith(this string format, IFormatProvider provider, object org0) { return format.FormatWith(provider, new object[] { org0 }); } public static string FormatWith(this string format, IFormatProvider provider, params object[] args) { DataValidate.ArgumentNotNull(format, "format"); return string.Format(provider, format, args); } }
二、ok,上面的代码完成了对string类的扩展,为其添加了两个扩展方法,下面经过代码来测试是否成功
string result = "'{0}' cannot empty".FormatWith(CultureInfo.InvariantCulture, "aaa"); Response.Write(result);
输出:
ok,说明实例方法扩展成功
总结:上面的扩展方法的调用方式,看上去像是成员方法,但实际编译器会对this关键字作特殊处理,编译器生成的中间语言(IL)会将代码转换为对静态方法的调用,
所以,并未真正违反封装原则。实际上,扩展方法没法访问它们所扩展的类型中的私有变量,不信你能够试试在扩展方法中访问string的私有成员!!!