日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【转】五、谈扩展方法的理解

發(fā)布時(shí)間:2025/3/21 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】五、谈扩展方法的理解 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

【轉(zhuǎn)】五、談擴(kuò)展方法的理解

為什么要用擴(kuò)展方法

在說什么是擴(kuò)展方法之前我們先來說說為什么要用擴(kuò)展方法。

首先我們定義一個(gè)?Person?類:

public class Person {/// <summary>/// 出生日期/// </summary>public DateTime BirthTime { get; set; }/// <summary>/// 死亡日期/// </summary>public DateTime? DeathTime { get; set; }//、、、、、、 }

加入這個(gè)類來自第三方的dll引用,且現(xiàn)在我們需要添加一個(gè)方法?GetAge?獲取年齡。你可能會想到自己定一個(gè)子類繼承:

public class MyPerson : Person {public int GetAge(){if (DeathTime.HasValue)return (DeathTime.Value - BirthTime).Days / 365;elsereturn (DateTime.Now - BirthTime).Days / 365;} }

是的,這樣可以實(shí)現(xiàn)我們的需求。不過實(shí)現(xiàn)新增的方法就去繼承真的是最合適的嗎(暫且不說)??如果上面定義的密封類呢??public sealed class Person?,這個(gè)時(shí)候是不能繼承的,我們只能另想辦法。

隨意寫個(gè)靜態(tài)類:

public static class ExtensionClass {public static int GetAge(Person person){if (person.DeathTime.HasValue)return (person.DeathTime.Value - person.BirthTime).Days / 365;elsereturn (DateTime.Now - person.BirthTime).Days / 365;}

然后調(diào)用? age = ExtensionClass.GetAge(p);?,是的看似不錯(cuò)。可是這和我們說的擴(kuò)展方法有什么關(guān)系呢?下面就是見證奇跡的時(shí)候了。

其他的任何地方都不變,唯一變化的是在參數(shù)前面加里this關(guān)鍵字。對,是的,僅僅如此它就變成了我們今天要講的擴(kuò)展方法。

調(diào)用如:? var age = p.GetAge();?相比上面的?age = ExtensionClass.GetAge(p);?更簡單明了。

這里我們說的是在需要擴(kuò)展密封類的方法時(shí),我們可以使用到擴(kuò)展方法。還有一種情況就是,在需要擴(kuò)展接口的時(shí)候時(shí)候我們更加需要。比如,需要擴(kuò)展IList的排序。我們要么寫個(gè)擴(kuò)展方法,要么是繼承實(shí)現(xiàn)接口(會強(qiáng)制要求實(shí)現(xiàn)接口下的所有方法)。我想你心中已經(jīng)有了答案選擇哪種方式。

擴(kuò)展方法到底是什么

我們看到上面使用的擴(kuò)展方法,有沒有感覺很神奇。僅僅多添加了一個(gè)this關(guān)鍵字就直接可以當(dāng)成擴(kuò)展方法使用了。那擴(kuò)展方法到底是什么東東,看了上面代碼好像和靜態(tài)方法有著說不清道不明的關(guān)系。下面我們繼續(xù)分析:

分別定義一個(gè)靜態(tài)方法和一個(gè)擴(kuò)展方法

public static class ExtensionClass{public static int GetAge2(Person person){if (person.DeathTime.HasValue)return (person.DeathTime.Value - person.BirthTime).Days / 365;elsereturn (DateTime.Now - person.BirthTime).Days / 365;}public static int GetAge(this Person person){if (person.DeathTime.HasValue)return (person.DeathTime.Value - person.BirthTime).Days / 365;elsereturn (DateTime.Now - person.BirthTime).Days / 365;}

分別調(diào)用:

var p = new Person() { BirthTime = DateTime.Parse("1990-07-19") }; var age = p.GetAge(); age = ExtensionClass.GetAge2(p);

編譯后的IL代碼:

我們看到反編譯成IL之后發(fā)現(xiàn)兩者并無不同。所以,我理解成(擴(kuò)展方法本質(zhì)上就是靜態(tài)方法,之所以出現(xiàn)擴(kuò)展方法是C#以另外一種形式表現(xiàn)靜態(tài)方法而已。只有有何妙用下面會繼續(xù)講解)。且?編譯后同樣帶上了靜態(tài)類名。

擴(kuò)展方法可以做些什么

  • 把已有的靜態(tài)方法轉(zhuǎn)成擴(kuò)展方法:如:
public static bool IsNullOrEmpty(this string str) {return string.IsNullOrEmpty(str); }

調(diào)用:?

string str = null; var isNull = str.IsNullOrEmpty();

?感覺相比期靜態(tài)方法調(diào)用要優(yōu)雅,更接近我們的自然語言。

  • ?可以編寫很多的幫助類,如(以string為例):
/// <summary>/// 轉(zhuǎn)DateTime /// </summary>/// <param name="str"></param>/// <returns></returns>public static DateTime? MyToDateTime(this string str){if (string.IsNullOrEmpty(str))return null;elsereturn DateTime.Parse(str);}/// <summary>/// 轉(zhuǎn)double/// </summary>/// <param name="str"></param>/// <returns></returns>public static double MyToDouble(this string str){if (string.IsNullOrEmpty(str))return -1;elsereturn double.Parse(str);}/// <summary>/// 轉(zhuǎn)int/// </summary>/// <param name="str"></param>/// <returns></returns>public static int MyToInt(this string str){if (string.IsNullOrEmpty(str))return -1;elsereturn int.Parse(str);}/// <summary>/// 指示指定的字符串是 null 還是 System.String.Empty 字符串。/// </summary>/// <param name="str"></param>/// <returns></returns>public static bool IsNullOrEmpty(this string str){return string.IsNullOrEmpty(str);}/// <summary>/// 如果字符串為null,則返回空字符串。(否則返回原字符串)/// </summary>/// <param name="str"></param>/// <returns></returns>public static string GetValueOrEmpty(this string str){if (str.IsNullOrEmpty())return string.Empty;return str;} View Code

上面所有的都只是擴(kuò)展方法的附加用處,擴(kuò)展方法真正的威力是為Linq服務(wù)的(主要體現(xiàn)于IEnumerable和IQueryable),實(shí)現(xiàn)鏈?zhǔn)骄幊獭O旅嫖覀冏约簛韺?shí)現(xiàn)所謂的鏈?zhǔn)骄幊?#xff1a;

初始化?Person?集合。

List<Person> persons = new List<Person>() {new Person(){ BirthTime=DateTime.Parse("1990-01-19")},new Person(){ BirthTime=DateTime.Parse("1993-04-17")},new Person(){ BirthTime=DateTime.Parse("1992-07-19"), DeathTime=DateTime.Parse("2010-08-18")},new Person(){ BirthTime=DateTime.Parse("1990-03-14")},new Person(){ BirthTime=DateTime.Parse("1991-08-15")},new Person(){ BirthTime=DateTime.Parse("1993-07-29")},new Person(){ BirthTime=DateTime.Parse("1991-06-19")} };

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

public static class ExtensionClass{/// <summary>/// 按條件查詢/// </summary>/// <typeparam name="T"></typeparam>/// <param name="list"></param>/// <param name="func"></param>/// <returns></returns>public static IList<T> MyWhere<T>(this IList<T> list, Func<T, bool> func){List<T> newList = new List<T>();foreach (var item in list){if (func(item))newList.Add(item);}return newList;}/// <summary>/// 升序排序/// </summary>/// <typeparam name="T"></typeparam>/// <param name="list"></param>/// <param name="func"></param>/// <returns></returns>public static IList<T> MyOrderBy<T>(this IList<T> list, Func<T, DateTime> func){if (list.Count() <= 1)return list;for (int i = 0; i < list.Count(); i++){for (int j = i + 1; j < list.Count(); j++){var item1 = list[j - 1];var item2 = list[j];if ((func(item1) - func(item2)).Ticks > 0){list[j - 1] = item2;list[j] = item1;}}}return list;}/// <summary>/// 降序排序/// </summary>/// <typeparam name="T"></typeparam>/// <param name="list"></param>/// <param name="func"></param>/// <returns></returns>public static IList<T> MyOrderByDescending<T>(this IList<T> list, Func<T, DateTime> func){if (list.Count() <= 1)return list;for (int i = 0; i < list.Count(); i++){for (int j = 1; j < list.Count() - i; j++){var item1 = list[j - 1];var item2 = list[j];if ((func(item1) - func(item2)).Ticks < 0){list[j - 1] = item2;list[j] = item1;}}}return list;}}

調(diào)用:(這里僅僅為了演示,所以不要討論實(shí)現(xiàn)是否合理、算法是否高效。

var newPersons = persons.MyWhere(t => t.DeathTime == null).MyOrderByDescending(t => t.BirthTime); foreach (var item in newPersons) {Console.WriteLine(item.BirthTime); }

就是如此簡單的實(shí)現(xiàn)了所謂的函數(shù)式編程。結(jié)果圖如下:

這樣一句代碼搞定所有邏輯,像自然語言般的流暢。其實(shí).net為IEnumerable實(shí)現(xiàn)了這樣的擴(kuò)展,如:

執(zhí)行結(jié)構(gòu)和上面一模一樣。

?

其實(shí)擴(kuò)展方法也可以當(dāng)成靜態(tài)方法來使用:

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

(不信?繼續(xù)看,有圖有真相)

?

C#代碼:

?

反編譯C#的代碼:(你是不是看到了,編譯后直接就是使用的擴(kuò)展方法的形式。

反編譯的IL代碼:

雖然編譯后的代碼是一樣的,但是做為程序員的我們更喜歡哪種方式呢?

?

總結(jié):

我們在對擴(kuò)展方法的怎么使用疑惑或者忘記了規(guī)則的時(shí)候,我們不用去查找資料說:

  • 第一個(gè)參數(shù)是要擴(kuò)展或者要操作的類型,這稱為"被擴(kuò)展的類型"
  • 為了指定擴(kuò)展方法,要在被擴(kuò)展的類型名稱前面附加this修飾符
  • 要將方法作為一個(gè)擴(kuò)展方法來訪問,要用using指令導(dǎo)入擴(kuò)展類型的命名空間,或者使擴(kuò)展類型和調(diào)用代碼在同一個(gè)命名空間中.
  • 我們只需記住,當(dāng)你不知道怎么編寫或使用擴(kuò)展方法時(shí),你先把它當(dāng)成靜態(tài)方法編寫或使用。如果可行,一般都可以轉(zhuǎn)成擴(kuò)展方法的形式。

    ?

    全部代碼:

    using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; using System.Data.Entity.Utilities; using System.Diagnostics.CodeAnalysis; using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using System.IO;namespace test {class Program{static void Main(string[] args){/* * 1.工具類* 2.鏈?zhǔn)骄幊?/span>*/string str = null;var isNull = str.IsNullOrEmpty();var p = new Person() { BirthTime = DateTime.Parse("1990-07-19") };var age = p.GetAge();age = ExtensionClass.GetAge2(p);List<Person> persons = new List<Person>() {new Person(){ BirthTime=DateTime.Parse("1990-01-19")},new Person(){ BirthTime=DateTime.Parse("1993-04-17")},new Person(){ BirthTime=DateTime.Parse("1992-07-19"), DeathTime=DateTime.Parse("2010-08-18")},new Person(){ BirthTime=DateTime.Parse("1990-03-14")},new Person(){ BirthTime=DateTime.Parse("1991-08-15")},new Person(){ BirthTime=DateTime.Parse("1993-07-29")},new Person(){ BirthTime=DateTime.Parse("1991-06-19")}};var newPersons = persons.MyWhere(t => t.DeathTime == null).MyOrderByDescending(t => t.BirthTime);var p1 = ExtensionClass.MyWhere(persons, t => t.DeathTime == null);var p2 = ExtensionClass.MyOrderByDescending(p1, t => t.BirthTime);var p3 = ExtensionClass.MyOrderBy(p2, t => t.BirthTime);foreach (var item in newPersons){Console.WriteLine(item.BirthTime);}Console.ReadKey();}}public sealed class Person{/// <summary>/// 出生日期/// </summary>public DateTime BirthTime { get; set; }/// <summary>/// 死亡日期/// </summary>public DateTime? DeathTime { get; set; }}//public class MyPerson : Person//{// public int GetAge()// {// if (DeathTime.HasValue)// return (DeathTime.Value - BirthTime).Days / 365;// else// return (DateTime.Now - BirthTime).Days / 365;// }//}public static class ExtensionClass{/// <summary>/// 按條件查詢/// </summary>/// <typeparam name="T"></typeparam>/// <param name="list"></param>/// <param name="func"></param>/// <returns></returns>public static IList<T> MyWhere<T>(this IList<T> list, Func<T, bool> func){List<T> newList = new List<T>();foreach (var item in list){if (func(item))newList.Add(item);}return newList;}/// <summary>/// 升序排序/// </summary>/// <typeparam name="T"></typeparam>/// <param name="list"></param>/// <param name="func"></param>/// <returns></returns>public static IList<T> MyOrderBy<T>(this IList<T> list, Func<T, DateTime> func){if (list.Count() <= 1)return list;for (int i = 0; i < list.Count(); i++){for (int j = i + 1; j < list.Count(); j++){var item1 = list[j - 1];var item2 = list[j];if ((func(item1) - func(item2)).Ticks > 0){list[j - 1] = item2;list[j] = item1;}}}return list;}/// <summary>/// 降序排序/// </summary>/// <typeparam name="T"></typeparam>/// <param name="list"></param>/// <param name="func"></param>/// <returns></returns>public static IList<T> MyOrderByDescending<T>(this IList<T> list, Func<T, DateTime> func){if (list.Count() <= 1)return list;for (int i = 0; i < list.Count(); i++){for (int j = 1; j < list.Count() - i; j++){var item1 = list[j - 1];var item2 = list[j];if ((func(item1) - func(item2)).Ticks < 0){list[j - 1] = item2;list[j] = item1;}}}return list;}public static int GetAge2(Person person){if (person.DeathTime.HasValue)return (person.DeathTime.Value - person.BirthTime).Days / 365;elsereturn (DateTime.Now - person.BirthTime).Days / 365;}public static int GetAge(this Person person){if (person.DeathTime.HasValue)return (person.DeathTime.Value - person.BirthTime).Days / 365;elsereturn (DateTime.Now - person.BirthTime).Days / 365;}public static bool IsNullOrEmpty(this string str){return string.IsNullOrEmpty(str);}} } View Code

    ?

    本文以同步至《C#基礎(chǔ)知識鞏固系列》

    轉(zhuǎn)載于:https://www.cnblogs.com/RYouHoo-923/p/8267517.html

    總結(jié)

    以上是生活随笔為你收集整理的【转】五、谈扩展方法的理解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 久久久久久久久99精品 | av毛片在线免费观看 | 欧美黄色一区二区三区 | 亚洲图片在线 | 亚洲第一精品网站 | 香蕉网站在线观看 | 夜夜免费视频 | 久久精品电影 | 99re视频这里只有精品 | wwwyoujizz日本| 欧美黄色片网站 | 国产精品一区二区不卡 | 91网站免费| 国产精品1 | 69av片| 国产网红av | 国产视频一区三区 | 欧美高h| 国产日韩欧美在线观看 | 爱操av| 国内自拍在线观看 | 国产精彩视频在线观看 | 亚洲综合视频一区 | 亚洲精品aⅴ中文字幕乱码 国产精品调教视频 | 超碰2020| 老司机在线永久免费观看 | 漂亮少妇高潮午夜精品 | 肉丝美足丝袜一区二区三区四 | 综合国产一区 | 91九色高潮 | 亚洲天堂一区二区在线 | caopeng在线 | 日本韩国三级 | 成人福利视频网站 | 在线xxxx| 亚洲区成人 | 毛片www| 火影黄动漫免费网站 | 欧美射射射| 国产精品日韩欧美大师 | 91亚洲欧美 | 日本五十肥熟交尾 | 春宵av | 精品国产区一区二 | 人妻无码一区二区三区 | 国产精品伦一区二区三级视频 | 一级特黄欧美 | 少妇脚交调教玩男人的视频 | 毛片高清免费 | 已满18岁免费观看电视连续剧 | 一个综合色 | 多啪啪免费视频 | 青青啪啪| 国产又爽又猛又粗的视频a片 | 日韩少妇一区二区三区 | 超碰在线免费看 | 日本高清视频一区二区 | 欧美另类tv | 欧美日韩在线视频一区 | 国产电影一区二区三区爱妃记 | 中国1级毛片| 李丽珍裸体午夜理伦片 | 大黄毛片 | 蜜桃视频久久 | 无码人妻丰满熟妇区五十路 | 精品日韩制服无码久久久久久 | 国产成人在线电影 | 影音先锋中文字幕一区二区 | 99久久精品一区二区成人 | 精品亚洲国产成人av制服丝袜 | 亚洲第一网站 | 理论片大全免费理伦片 | 午夜免费福利网站 | 国产在线一区二区三区四区 | 精品一区二区久久久久久按摩 | 亚洲第一av网站 | 亚洲666 | 国产亚洲精品电影 | 尤物精品在线观看 | 亚洲va天堂va国产va久 | 色屁屁草草影院ccyycom | 大胸美女无遮挡 | 激情视频区 | 欧美三级在线观看视频 | 极品超粉嫩尤物69xx | 亚洲一区二区三区影院 | 国产美女激情 | 自拍偷在线精品自拍偷无码专区 | 韩国毛片网站 | 色综合久久久久久久 | 性插动态视频 | 神马久久久久久 | 日韩欧美一级二级 | 一级黄色大片视频 | 波多野结衣办公室双飞 | 国产成人av免费看 | 天堂影视在线观看 | 成人羞羞免费 | 探花视频在线观看 |