您好,欢迎访问三七文档
C#3.0中的扩展方法(ExtensionMethods)扩展方法的定义,需要注意三个部分:1、静态类(私有公共都可以);2、静态方法(私有公共都可以);3、第一个函数参数前带this(必须是第一参数前)namespaceHongjun.Guo{staticclassMyExtensionMethods{internalstaticvoidPrint(thisobjects){Console.WriteLine(s);}}}扩展方法的使用,需要注意点:using你定义所在的命名空间。usingHongjun.Guo;staticvoidMain(string[]args){objecto=dsdgs;o.Print();}这样一个简简单单的代码后,我们就可以很方便的对一些不开源的第三方控件增加很多我们自己额外需要的功能。扩展方法的使用,有时候并不是这么简简单单,我们来看一些特殊情况,通过这些特殊情况的分析,我们可以更深入的了解扩展方法:情况一:扩展方法跟原来类的方法重名时候的处理逻辑。场景:我们是对一个第三方的没有开放源代码组件的一个类扩展了一个方法,比如方法:Print。过了一段时间后,这个第三方的组件发布了新版本,该类的增加了Print方法。这时候会出何种效果??问题演示代码:namespaceHongjun.Guo{publicclassMyClass{publicvoidPrint(){Console.WriteLine(****);}}staticclassMyExtensionMethods{internalstaticvoidPrint(thisMyClasss){Console.WriteLine(haha+s.ToString());}}}调用范例:usingHongjun.Guo;staticvoidMain(string[]args){MyClasso=newMyClass();o.Print();Console.ReadLine();}这时候我们会看到何种结果呢??答案:看到的是****也就是,扩展方法跟类的方法冲突时候,编译使用不会报任何错误,这时候以类的方法优先级最高,这时我们使用类的方法,而不是扩展方法。分析:我们把上述两组代码编译后,再反编译成IL,我们就可以看到,实际上,扩展方法在IL层上是不存在的。扩展方法实际是编译器调用某个类的某个方法的时候,先去这个类找,如果有这个方法,则就调用;如果找不到,根据引用的命名空间,再去找扩展方法(静态类的静态方法)。找到,就使用,找不到当然就编译错误了。根据这个分析结果,我们就可以理解上述问题处理的结果了情况二:扩展方法的嵌套比如我们有如下扩展方法。namespaceHongjun.Guo{staticclassMyExtensionMethods{publicstaticintTest01(thisinti){returni*3;}publicstaticintTest02(thisinti){returni+5;}}}下面是调用范例:staticvoidMain(string[]args){intmm=7;Console.WriteLine(mm.Test01().Test02());Console.WriteLine(*****);Console.WriteLine(mm.Test02().Test01());Console.WriteLine(*****);Console.WriteLine(MyExtensionMethods.Test02(MyExtensionMethods.Test01(mm)));Console.ReadLine();}问,调用的显示结果是何值?答案:依次显示:26,36,26分析:mm.Test01().Test02()这行代码编译后相当于如下代码:MyExtensionMethods.Test02(MyExtensionMethods.Test01(mm))这两行代码在编译后的IL中是完全一样的。C#扩展方法学习经验C#新语言特性有很多值得学习的地方,这里我们主要介绍C#扩展方法,包括介绍通过usingnamespace来导入其它命名空间中的扩展方法等方面。C#扩展方法(ExtensionMethods)往往我们需要对CLR类型进行一些操作,但苦于无法扩展CLR类型的方法,只能创建一些helper方法,或者继承类。我们来修改上面的User类:1.publicclassUser2.{3.publicintId{get;set;}4.publicstringName{get;set;}5.publicintAge{get;set;}6.publicstringRead()7.{8.returnId:+Id+姓名:+Name+年龄:+Age;9.}10.}然后调用1.varuser=new{Id=1,Name=YJingLee,Age=22};2.varstr=user.Read();现在有了扩展方法就方便多了。扩展方法允许开发人员往一个现有的CLR类型的公开契约(contract)中添加新的方法,而不用生成子类或者重新编译原来的类型。扩展方法有助于把今天动态语言中流行的对ducktyping的支持之灵活性,与强类型语言之性能和编译时验证融合起来。——引用Scott博文扩展方法是可以通过使用实例方法语法调用的静态方法。效果上,使得附加的方法扩展已存在类型和构造类型成为可能。他可以对现有类功能进行扩充,从而使该类型的实例具有更多的方法(功能)。扩展方法允许我们在不改变源代码的情况下扩展(即添加不能修改)现有类型中的实例方法。扩展方法给我们一个怎样的思路呢?我们一步一步做一下!首先声明扩展方法:通过指定关键字this修饰方法的第一个参数。注意扩展方法仅可声明在静态类中。扩展方法具备所有常规静态方法的所有能力,可以使用实例方法语法来调用。接着就可以调用扩展方法了。下面通过一个具体的实例分析一下:例如我们要检查一个字符串变量是否是合法的电子邮件地址?在.Net2.0框架下像这样:1.varemail=leeyongjing@gmail.com;2.if(EmailValidator.IsValid(email))3.{4.Response.Write(YJingLee提示:这是一个正确的邮件地址);5.}而使用C#扩展方法的话,我可以添加“IsValidEmailAddress()”方法到string类本身中去,该方法返回当前字符串实例是否是个合法的字符串。1.if(email.IsValidEmailAddress())2.{3.Response.Write(YJingLee提示:这是一个正确的邮件地址);4.}我们是怎么把这个IsValidEmailAddress()方法添加到现有的string类里去的呢?先定义一个静态类,再定义“IsValidEmailAddress”这个静态的法来实现的。1.publicstaticclassExtensions//静态类2.{3.publicstaticboolIsValidEmailAddress(thisstrings)4.//静态方法和this5.{6.Regexregex=newRegex(@^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$);7.returnregex.IsMatch(s);8.}9.}注意,上面的静态方法在第一个类型是string的参数变量前有个“this”关键词,这告诉编译器,这个特定的扩展方法应该添加到类型为“string”的对象中去。然后在IsValidEmailAddress()方法实现里,我可以访问调用该方法的实际string实例的所有公开属性/方法/事件,取决于它是否是合法电子邮件地址来返回true/false。C#扩展方法不仅能够应用到个别类型上,也能应用到.NET框架中任何基类或接口上。即可用于整个.NET框架丰富的可组合的框架层扩展。扩展方法要点1.扩展方法的本质为将实例方法调用在编译期改变为静态类中的静态方法调用。事实上,它确实拥有静态方法所具有的所有功能。2.扩展方法的作用域是整个namespace可见的,并且可以通过usingnamespace来导入其它命名空间中的扩展方法。3.扩展方法的优先级:现有实例方法优先级最高,其次为最近的namespace下的静态类的静态方法,最后为较远的namespace下的静态类的静态方法。4.扩展方法是一种编译时技术,注意与反射等运行时技术进行区别,并慎重使用。
本文标题:C#-扩展方法
链接地址:https://www.777doc.com/doc-4706090 .html