五、谈扩展方法的理解

前端之家收集整理的这篇文章主要介绍了五、谈扩展方法的理解前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

为什么要用扩展方法

在说什么是扩展方法之前我们先来说说为什么要用扩展方法

首先我们定义一个  类:

DateTime BirthTime { ; DateTime? DeathTime { ; }

加入这个类来自第三方的dll引用,且现在我们需要添加一个方法  获取年龄。你可能会想到自己定一个子类继承:

(DeathTime.Value - BirthTime).Days / (DateTime.Now - BirthTime).Days /

是的,这样可以实现我们的需求。不过实现新增的方法就去继承真的是最合适的吗()? 如果上面定义的密封类呢?  Person ,这个时候是不能继承的,我们只能另想办法。

随意写个静态类:

(person.DeathTime.Value - person.BirthTime).Days / (DateTime.Now - person.BirthTime).Days /

然后调用  ,是的看似不错。可是这和我们说的扩展方法有什么关系呢?下面就是见证奇迹的时候了。

其他的任何地方都不变,唯一变化的是在参数前面加里this关键字。对,是的,仅仅如此它就变成了我们今天要讲的扩展方法

调用如:  age = p.GetAge(); 相比上面的  更简单明了。

这里我们说的是在需要扩展密封类的方法时,我们可以使用到扩展方法。还有一种情况就是,在需要扩展接口的时候时候我们更加需要。比如,需要扩展IList的排序。我们要么写个扩展方法,要么是继承实现接口(方法)。我想你心中已经有了答案选择哪种方式。

扩展方法到底是什么

我们看到上面使用的扩展方法,有没有感觉很神奇。仅仅多添加了一个this关键字就直接可以当成扩展方法使用了。那扩展方法到底是什么东东,看了上面代码好像和静态方法有着说不清道不明的关系。下面我们继续分析:

分别定义一个静态方法和一个扩展方法

(person.DeathTime.Value - person.BirthTime).Days / (DateTime.Now - person.BirthTime).Days / </span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;static</span> <span style="color: #0000ff;"&gt;int</span> GetAge(<span style="color: #0000ff;"&gt;this</span><span style="color: #000000;"&gt; Person person) { </span><span style="color: #0000ff;"&gt;if</span><span style="color: #000000;"&gt; (person.DeathTime.HasValue) </span><span style="color: #0000ff;"&gt;return</span> (person.DeathTime.Value - person.BirthTime).Days / <span style="color: #800080;"&gt;365</span><span style="color: #000000;"&gt;; </span><span style="color: #0000ff;"&gt;else</span> <span style="color: #0000ff;"&gt;return</span> (DateTime.Now - person.BirthTime).Days / <span style="color: #800080;"&gt;365</span><span style="color: #000000;"&gt;; }</span></pre>

分别调用

p = Person() { BirthTime = DateTime.Parse( age == ExtensionClass.GetAge2(p);

编译后的IL代码

我们看到反编译成IL之后发现两者并无不同。所以,我理解成(方法本质上就是静态方法,之所以出现扩展方法是C#以另外一种形式表现静态方法而已。只有有何妙用下面会继续讲解)。且 

扩展方法可以做些什么

IsNullOrEmpty(

调用: 

str = isNull = str.IsNullOrEmpty();

 感觉相比期静态方法调用要优雅,更接近我们的自然语言。

  •  可以编写很多的帮助类,如():

上面所有的都只是扩展方法的附加用处,扩展方法真正的威力是为Linq服务的(),实现链式编程。下面我们自己来实现所谓的链式编程:

初始化 

List persons = List Person(){ BirthTime=DateTime.Parse( Person(){ BirthTime=DateTime.Parse( Person(){ BirthTime=DateTime.Parse(),DeathTime=DateTime.Parse( Person(){ BirthTime=DateTime.Parse( Person(){ BirthTime=DateTime.Parse( Person(){ BirthTime=DateTime.Parse( Person(){ BirthTime=DateTime.Parse(

需求:1.查询活人。2.按出生日期排序

查询 IList MyWhere( IList list,Func> newList = List ( item </span><span style="color: #808080;"&gt;///</span> <span style="color: #808080;"&gt;<summary></span> <span style="color: #808080;"&gt;///</span><span style="color: #008000;"&gt; 升序排序 </span><span style="color: #808080;"&gt;///</span> <span style="color: #808080;"&gt;</summary></span> <span style="color: #808080;"&gt;///</span> <span style="color: #808080;"&gt;<typeparam name="T"&gt;</typeparam></span> <span style="color: #808080;"&gt;///</span> <span style="color: #808080;"&gt;<param name="list"&gt;</param></span> <span style="color: #808080;"&gt;///</span> <span style="color: #808080;"&gt;<param name="func"&gt;</param></span> <span style="color: #808080;"&gt;///</span> <span style="color: #808080;"&gt;<returns></returns></span> <span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;static</span> IList<T> MyOrderBy<T>(<span style="color: #0000ff;"&gt;this</span> IList<T> list,DateTime><span style="color: #000000;"&gt; func) { </span><span style="color: #0000ff;"&gt;if</span> (list.Count() <= <span style="color: #800080;"&gt;1</span><span style="color: #000000;"&gt;) </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; list; </span><span style="color: #0000ff;"&gt;for</span> (<span style="color: #0000ff;"&gt;int</span> i = <span style="color: #800080;"&gt;0</span>; i < list.Count(); i++<span style="color: #000000;"&gt;) { </span><span style="color: #0000ff;"&gt;for</span> (<span style="color: #0000ff;"&gt;int</span> j = i + <span style="color: #800080;"&gt;1</span>; j < list.Count(); j++<span style="color: #000000;"&gt;) { </span><span style="color: #0000ff;"&gt;var</span> item1 = list[j - <span style="color: #800080;"&gt;1</span><span style="color: #000000;"&gt;]; </span><span style="color: #0000ff;"&gt;var</span> item2 =<span style="color: #000000;"&gt; list[j]; </span><span style="color: #0000ff;"&gt;if</span> ((func(item1) - func(item2)).Ticks > <span style="color: #800080;"&gt;0</span><span style="color: #000000;"&gt;) { list[j </span>- <span style="color: #800080;"&gt;1</span>] =<span style="color: #000000;"&gt; item2; list[j] </span>=<span style="color: #000000;"&gt; item1; } } } </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; list; } </span><span style="color: #808080;"&gt;///</span> <span style="color: #808080;"&gt;<summary></span> <span style="color: #808080;"&gt;///</span><span style="color: #008000;"&gt; 降序排序 </span><span style="color: #808080;"&gt;///</span> <span style="color: #808080;"&gt;</summary></span> <span style="color: #808080;"&gt;///</span> <span style="color: #808080;"&gt;<typeparam name="T"&gt;</typeparam></span> <span style="color: #808080;"&gt;///</span> <span style="color: #808080;"&gt;<param name="list"&gt;</param></span> <span style="color: #808080;"&gt;///</span> <span style="color: #808080;"&gt;<param name="func"&gt;</param></span> <span style="color: #808080;"&gt;///</span> <span style="color: #808080;"&gt;<returns></returns></span> <span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;static</span> IList<T> MyOrderByDescending<T>(<span style="color: #0000ff;"&gt;this</span> IList<T> list,DateTime><span style="color: #000000;"&gt; func) { </span><span style="color: #0000ff;"&gt;if</span> (list.Count() <= <span style="color: #800080;"&gt;1</span><span style="color: #000000;"&gt;) </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; list; </span><span style="color: #0000ff;"&gt;for</span> (<span style="color: #0000ff;"&gt;int</span> i = <span style="color: #800080;"&gt;0</span>; i < list.Count(); i++<span style="color: #000000;"&gt;) { </span><span style="color: #0000ff;"&gt;for</span> (<span style="color: #0000ff;"&gt;int</span> j = <span style="color: #800080;"&gt;1</span>; j < list.Count() - i; j++<span style="color: #000000;"&gt;) { </span><span style="color: #0000ff;"&gt;var</span> item1 = list[j - <span style="color: #800080;"&gt;1</span><span style="color: #000000;"&gt;]; </span><span style="color: #0000ff;"&gt;var</span> item2 =<span style="color: #000000;"&gt; list[j]; </span><span style="color: #0000ff;"&gt;if</span> ((func(item1) - func(item2)).Ticks < <span style="color: #800080;"&gt;0</span><span style="color: #000000;"&gt;) { list[j </span>- <span style="color: #800080;"&gt;1</span>] =<span style="color: #000000;"&gt; item2; list[j] </span>=<span style="color: #000000;"&gt; item1; } } } </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; list; } }</span></pre>

调用:(

newPersons = persons.MyWhere(t => t.DeathTime == ).MyOrderByDescending(t => ( item

就是如此简单的实现了所谓的函数式编程。结果图如下:

这样一句代码搞定所有逻辑,像自然语言般的流畅。其实.net为IEnumerable实现了这样的扩展,如:

403caedf8083d0590ceb02eea748.png" alt="">

执行结构和上面一模一样。

其实扩展方法也可以当成静态方法来使用:

p1 = ExtensionClass.MyWhere(persons,t => t.DeathTime == p2 = ExtensionClass.MyOrderByDescending(p1,t => p3 = ExtensionClass.MyOrderBy(p2,t => t.BirthTime);

C#代码

 

反编译C#的代码:(方法的形式。

反编译的IL代码

301c4e7ba6b56c4.png" alt="">

虽然编译后的代码是一样的,但是做为程序员的我们更喜欢哪种方式呢?

我们在对扩展方法的怎么使用疑惑或者忘记了规则的时候,我们不用去查找资料说:

  1. 第一个参数是要扩展或者要操作的类型,这称为"被扩展的类型"
  2. 为了指定扩展方法,要在被扩展的类型名称前面附加this修饰符
  3. 要将方法作为一个扩展方法来访问,要用using指令导入扩展类型的命名空间,或者使扩展类型和调用代码在同一个命名空间中.

方法时,你先把它当成静态方法编写或使用。如果可行,一般都可以转成扩展方法的形式。

全部代码

本文以同步至《

猜你在找的C#相关文章