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

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

(转)c# 扩展方法的更多相关文章

  1. .NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法

    .NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法 0x00 为什么需要Map(MapWhen)扩展 如果业务逻辑比较简单的话,一条主管道就够了,确实用不到 ...

  2. .NET Core中间件的注册和管道的构建(2)---- 用UseMiddleware扩展方法注册中间件类

    .NET Core中间件的注册和管道的构建(2)---- 用UseMiddleware扩展方法注册中间件类 0x00 为什么要引入扩展方法 有的中间件功能比较简单,有的则比较复杂,并且依赖其它组件.除 ...

  3. 为IEnumerable<T>添加RemoveAll<IEnumerable<T>>扩展方法--高性能篇

    最近写代码,遇到一个问题,微软基于List<T>自带的方法是public bool Remove(T item);,可是有时候我们可能会用到诸如RemoveAll<IEnumerab ...

  4. C#的扩展方法解析

    在使用面向对象的语言进行项目开发的过程中,较多的会使用到“继承”的特性,但是并非所有的场景都适合使用“继承”特性,在设计模式的一些基本原则中也有较多的提到. 继承的有关特性的使用所带来的问题:对象的继 ...

  5. 扩展方法(C#)

    扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型.扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用. 下面的示例为String添加 ...

  6. 扩展方法解决LinqToSql Contains超过2100行报错问题

    1.扩展方法 using System; using System.Collections.Generic; using System.Linq; using System.Web; using Sy ...

  7. C#扩展方法

    扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型. 扩展方法就相当于一个马甲,给一个现有类套上,就可以为这个类添加其他方法了. 马甲必须定义为stati ...

  8. 枚举扩展方法获取枚举Description

    枚举扩展方法 /// <summary> /// 扩展方法,获得枚举的Description /// </summary> /// <param name="v ...

  9. 扩展方法 1 简单的string扩展方法

    这里是关于 String的简单扩展方法 (静态类 静态方法 this 类型 这里是string) static class Program { static void Main(string[] ar ...

  10. C#中的扩展方法

    扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型. 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用. 以上是msdn官网对扩展方 ...

随机推荐

  1. Java能抵挡住JavaScript的进攻吗?

    JavaScript的进攻 公元2014年,Java 第八代国王终于登上了王位. 第一次早朝,国王坐在高高的宝座上,看着毕恭毕敬的大臣,第一次体会到了皇权的威力. 德高望重的IO大臣颤悠悠地走上前来: ...

  2. MFC中的CString类使用方法指南

    MFC中的CString类使用方法指南 原文出处:codeproject:CString Management [禾路:这是一篇比较老的资料了,但是对于MFC的程序设计很有帮助.我们在MFC中使用字符 ...

  3. 基于快速排序思想partition查找第K大的数或者第K小的数。

    快速排序 下面是之前实现过的快速排序的代码. function quickSort(a,left,right){ if(left==right)return; let key=partition(a, ...

  4. Codeforces 235C Cyclical Quest - 后缀自动机

    Some days ago, WJMZBMR learned how to answer the query "how many times does a string x occur in ...

  5. docker 给运行的容器映射本地端口

    1.提交运行中的容器为一个镜像   (这样不会丢失在容器的各种操作) docker commit  tang     tang1 ###  tang(运行容器名称)   tang1(生成镜像名称) 2 ...

  6. topcoder srm 400 div1

    problem1 link 枚举指数,然后判断是不是素数即可. problem2 link 令$f[len][a][b][r]$(r=0或者1)表示子串$init[a,a+len-1]$匹配$goal ...

  7. 解决跨域(CORS)问题

    为什么会有跨域问题 是因为浏览器的同源策略是对ajax请求进行阻拦了,但是不是所有的请求都给做跨域,像是一般的href属性,a标签什么的都不拦截 解决跨域问题的两种方式 JSONP   推荐参考 CO ...

  8. How Flyway works

    The easiest scenario is when you point Flyway to an empty database. It will try to locate its schema ...

  9. (转)看穿机器学习(W-GAN模型)的黑箱

        本文转自:http://www.360doc.com/content/17/0212/11/35919193_628410589.shtml#   看穿机器学习(W-GAN模型)的黑箱 201 ...

  10. [蓝桥] 算法训练 P0505

    时间限制:1.0s 内存限制:256.0MB 一个整数n的阶乘可以写成n!,它表示从1到n这n个整数的乘积.阶乘的增长速度非常快,例如,13!就已经比较大了,已经无法存放在一个整型变量中:而35!就更 ...