扩展方法能够向现有类型“添加”方法,而无需创建新的派生类型,重新编译或以其他方式修改原始类型。扩展方法必须是静态方法,可以像实例方法一样进行调用。且调用同名中实际定义的方法优先级要高于扩展方法。

先来看看在经常使用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

最新文章

  1. 天津政府应急系统之GIS一张图(arcgis api for flex)讲解(一)GIS一张图的系统开发环境以及flexviewer框架
  2. css3之自定义字体
  3. (七)HTTP协议
  4. JSON对象遍历方法
  5. 2014多校第一场 E 题 || HDU 4865 Peter&#39;s Hobby (DP)
  6. c#语法笔记
  7. Bzoj 3781: 小B的询问 莫队,分块,暴力
  8. JavaScript函数柯里化的一些思考
  9. Linux 内核开发 - 进程空间
  10. SLC和MLC
  11. 解析.NET对象的跨应用程序域访问(下篇)
  12. 配置rsync+inotify实时同步
  13. arcgis api 4.x for js 结合 react 入门开发系列&quot;esri-loader&quot;篇(附源码下载)
  14. C# 给一个控件去掉焦点
  15. C语言基础一(敲打键盘、寻找资料)
  16. laravel5.8笔记三:常用命令
  17. 关于c++11中的thread库
  18. (二 -1) 天猫精灵接入Home Assistant-控制Mqtt设备
  19. elasticsearch-head连接不上es
  20. JQ遇到$(‘.xxx’).attr(‘display’)一直返回undefined

热门文章

  1. k8s API sample
  2. 【python021-函数lambda表达式】
  3. 终于掌握vim的寄存器和系统剪贴板的使用了- 要安装vim-X11包
  4. 【做题】TCSRM591 Div1 500 PyramidSequences——数形结合&amp;思维
  5. oracle 之 创,增,删,改操作
  6. Asp.Net 之 DropDownList的使用
  7. LuoguP2257 YY的GCD
  8. BZOJ2956: 模积和
  9. 文件IO(2)
  10. BZOJ 2809: [Apio2012]dispatching(左偏树)