还记得我们看了好几遍的LINQ吧,下面这个:
- var numQuery =
- from num in numbers
- where (num % 2) == 0
- select num;
第一次讨论的时候我们讲到它等同于:
- IEnumerable<int> numQuery = numbers.Where((number) => number % 2 == 0);
如果用2.0很熟悉的朋友,会知道Where函数是3.0新增的,同时新增的还有Sum,Count等一系列方法,在MSDN 2008中,我们可以看到这些函数归属于IEnumerable
我们暂且先不讨论这个,先看看Array,List
我们再仔细看看MSDN,在每个IEnumerable
其实,这就是3.0中新增的扩展函数,扩展函数是一个非常非常有用的东西,它可以通过一个自定义的类扩展其他类的方法。例如:
- class ClassNeedExtensionMethod { }
- static class ClassHasExtensionMethod
- {
- public static void ExtensionMethod(this ClassNeedExtensionMethod cn)
- {
- Console.WriteLine("Extension Method Invoked!");
- }
- }
- class ExtensionMethodTester
- {
- public void Test()
- {
- ClassNeedExtensionMethod cn = new ClassNeedExtensionMethod();
- // 调用扩展方法 方式一
- cn.ExtensionMethod();
- // 调用扩展方法 方式二
- ClassHasExtensionMethod.ExtensionMethod(cn);
- }
- }
ClassNeedExtensionMethod是一个空空如也的类,但是在ExtensionMethodTester中却可以调用ExtensionMethod方法!这个方法是在ClassHasExtensionMethod中定义的!
情况是不是和IEnumerable
不过扩展函数必须是在一个静态类中,并且自身也必须是一个静态函数,调用方法有两种,在上面的代码中已经用红字标出了。
扩展函数的出现能解决什么情况?不需要通过类继承的方式来继承某些函数了!
首先我们都知道,一个类只能继承自一个类,但是可以扩展无数个(理论上,不过谁有真的会给一个类继承无数接口呢……)接口。如果你发现类A,类B已经继承自类P,但是又要给A B都再继承一个父类C(这种情况是非常常见的,在项目中再普遍不过了),2.0唯一的做法就是:追根溯源,让P继承自C。万一P又已经继承自M,怎么办?最恶劣的情况,P继承自Page!难道你要让Page类继承自你的C类吗?你和微软商量去,这便导致了父类继承的最经典的情况。
但是有了扩展函数,如果只是要继承方法,而不需要继承变量的话,我们只需要扩展一个接口IC,然后帮IC扩展函数,那A B就具有这个已经定义好的函数了,完全不再需要考虑父类继承问题。
最经典的应用场景:0/R Mapping框架 ActiveRecord,本来需要继承父类以具有Save等方法,但是这样等于限制了以后的类继承条件,现在我们可以改良,使用IActiveRecord,然后帮IActiveRecord扩展Save方法,同样能造成相同的使用而不会影响下层代码的改动,而且不再继承自任何父类!
扩展函数,.NET 3.0第三个以人为本的典例。
事实上……小凡觉得微软可能也发现使用LINQ后集合类需要扩展很多方法,但是也出现了类继承问题,于是绞尽脑汁想出了这个扩展函数的解决方案。不管怎么说,这个解决方案很巧妙,的确从根本出发解决了很多问题。