扩展方法能够向现有类型“添加”方法,而无需创建新的派生类型,重新编译或以其他方式修改原始类型。扩展方法必须是静态方法,可以像实例方法一样进行调用。且调用同名中实际定义的方法优先级要高于扩展方法。
先来看看在经常使用List类型中使用扩展方法的例子,首先看看List是如何定义的:
// 摘要: // Represents a strongly typed list of objects that can be accessed by index. // Provides methods to search, sort, and manipulate lists.To browse the .NET // Framework source code for this type, see the Reference Source. // // 类型参数: // T: // The type of elements in the list. [Serializable] [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))] public class List<T> : IList<T>, ICollection<T>, IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable { // 摘要: // Initializes a new instance of the System.Collections.Generic.List<T> class // that is empty and has the default initial capacity. [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] public List(); // // 摘要: // Initializes a new instance of the System.Collections.Generic.List<T> class // that contains elements copied from the specified collection and has sufficient // capacity to accommodate the number of elements copied. // // 参数: // collection: // The collection whose elements are copied to the new list. // // 异常: // System.ArgumentNullException: // collection is null. public List(IEnumerable<T> collection); …… }
在List的类型定义中我们并没有看到有定义Union方法的地方,但是当我们在调用的时候就会出现:
<span style="white-space:pre"> </span>/// <summary> /// 通过集合使用 /// </summary> /// <param name="needSearchList"></param> /// <param name="areaid"></param> /// <returns></returns> public List<AreaLineInfoModel> UseSetSearchCollection(List<AreaLineInfoModel> needSearchList, int areaid) { if (needSearchList == null || !needSearchList.Any()) return null; const int area15 = 15; var area15List = new List<AreaLineInfoModel>(); const int area16 = 16; var area16List = new List<AreaLineInfoModel>(); const int area17 = 17; var area17List = new List<AreaLineInfoModel>(); needSearchList.ForEach( m => { if (m.AreaIdList.Contains(area15)) area15List.Add(m); if (m.AreaIdList.Contains(area16)) area16List.Add(m); if (m.AreaIdList.Contains(area17)) area17List.Add(m); }); if (areaid == area15) return area15List.Union(area16List).Union(area17List).ToList(); if (areaid == area16) return area16List.Union(area15List).Union(area17List).ToList(); if (areaid == area17) return area17List.Union(area15List).Union(area16List).ToList(); return null; }
其中的Union方法哪里来的呢?我们转到定义看一看:
namespace System.Linq { public static class Enumerable { …… public static IEnumerable<TSource> Union<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second) { if (first == null) throw Error.ArgumentNull("first"); if (second == null) throw Error.ArgumentNull("second"); return UnionIterator<TSource>(first, second, null); } } }
so,也就是说,List的一个实例里面可以调用Enumerable里面的Union方法,如果我们不知道有扩展方法这回事的时候,以通常的想法,通过继承关系来找Union方法,会发现,List并没有实现Union方法,而且在继承的接口中也没有定义Union方法。这就比较纳闷了,这不是违背了面向对象的三大基本原则么?此话后说,我们先来自己实现一个扩展方法:
public interface IFreshList<T> { } public static class testjinni { public static IFreshList<TSource> Union<TSource>(this IFreshList<TSource> first, IFreshList<TSource> second) { return second; } } public class MyList<T> : IFreshList<T> { } public class use { public void meth() { var temiList=new MyList<int>(); var mdaidnnf = new MyList<int>(); temiList.Union(mdaidnnf); } }
这只是一个简单的例子,你可以做你自己的扩展方法。
所有对象都能使用扩展:
public static class ExtendExt
{
public static void FuncExt(this object obj)
{
int b = 0;
}
}
msdn是这样规定扩展方法的:“扩展方法被定义为静态方法,但它们是通过实例方法语法进行调用的。 它们的第一个参数指定该方法作用于哪个
类型,并且该参数以 this 修饰符为前缀。”通俗的说就是,扩展方法跟静态类的名称无关,只需要在一个静态类里面定义一个静态方法,第一个参数必须this T开头,
这个T就是一个泛型类型了。
小结:
本质上来说: 扩展方法是破坏原来的层次结构,通过网络结构加快业务逻辑处理;
扩展方法不改变被扩展类的代码,不用重新编译、修改、派生被扩展类;
扩展方法不能访问被扩展类的私有成员;
扩展方法会被被扩展类的同名方法覆盖,所以实现扩展方法我们需要承担随时被覆盖的风险;
扩展方法看似实现了面向对象中扩展对修改说不的特性,但是也违背了面向对象的继承原则,被扩展类的派生类是不能继承扩展扩展方法的,从而又违背了面向对象的多态性。;
在我们稳定的引用同一个版本的类库,但是我们没有该类库的源代码,那么我们可以使用扩展方法;但是从项目的可扩展、可维护和版本控制方面来说,都不建议使用扩展方法进行类的扩展。
文章转载自:https://blog.csdn.net/qin_zhangyongheng/article/details/52469476