小天:除了使用分部类的方式,还有什么办法可以扩展已有的类没有?
老田:还有许多方法扩展类。如果有类的源代码,使用继承(后面章节讨论)就是给对象添加功能的好方法。但如果没有源代码则可以使用扩展方法,扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。换句话说,它允许改变一个类,但不需要类的源代码。
扩展方法是静态方法,是类的一部分,但实际上没有放在类的源代码中。还记得在本章开始的那个oopTool命名空间下的User类吧。现在我们再新的项目中去引用oopTool。但是接下来,我们需要做的是扩展User类,首先需要创建一个静态类,至于这个类的名称,推荐使用“要扩展类名 + Extension”的方式命名。在类中创建一个静态方法,代码如下:
using System; using oopTool; public static class UserExtension { ///<summary> ///为User扩展一个方法,根据用户名和年龄来判断用户是否存在 ///</summary> ///<param name="user">this User user表示这个方法是User类的扩展方法</param> public static bool Exists(this User user,string name,int age) { if (user._name == name || user._age == age) return true; else return false; } } |
注意GetUser方法的参数。对于扩展方法,第一个参数是要扩展的类型,它放在this关键字的后面。这告诉编译器,这个方法是User类型的一部分。在这个例子中,User是要扩展的类型。在扩展方法中,可以访问所扩展类型的所有公共方法和属性。但是无法访问它们所扩展的类型中的私有变量。
另外,在代码中,可以使用实例方法语法调用该扩展方法。在主程序中,Exists方法看起来像是另一个方法。它没有显示第一个参数,也不能对它进行任何处理。要使用新方法,需要执行如下调用,这与其他方法相同:
//下面是展示如何使用到上面扩展类 User u = new User(); u._name = "thc"; u._age = 29; bool tf = u.Exists("天轰穿", 30); //调用User类的扩展方法Exists MessageBox.Show(tf.ToString()); //tf = false,为什么? |
从使用的方法来看,即使扩展方法是静态的,也要使用标准的实例方法语法。注意这里使用u实例变量来调用Exists方法,而没有使用类型名。因为编译器生成的中间语言 (IL) 会将代码转换为对静态方法的调用。因此,并未真正违反封装原则。
注意:如果扩展方法与类中的某个方法同名,扩展方法就从来不会被调用。类中已有的实例方法优先。
此文章为天轰穿原创作品,转载请注明出处及作者。