国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

.NET擴展方法(二)

2019-11-14 16:28:19
字體:
來源:轉載
供稿:網友

上一篇隨筆 .NET 擴展方法 (一) 已經對 擴展方法有了大致的介紹,這篇算是一個補充,讓我們來看一下擴展方法的幾個細節:

 

一、擴展方法具有繼承性

當使用擴展方法擴展一個類型的時候,其也擴展了派生類,所以上一篇的遺留問題“如果給object添加一個擴展方法會出現什么效果呢?” 的

答案就是——所有類型都將擴展該方法。object類已經經受住了時間的考驗,我們似乎也找不到更合適的理由來擴展object類。從另外的

角度考慮,如果擴展了object類,很有可能會給“智能敏感提示”造成污染,以至于填充了過多的垃圾信息(因為許多類型也根本用不到該方法)。

 

二、擴展方法允許和擴展類型原有方法相等效的方法存在 (此處是個雷)

由于漢語語言表述的所帶來的不易理解性,我們還是直接用代碼來解釋吧,如下的代碼片段:

    public static class StringExtentsion    {        public static string ToString(this string str)        {            return "Extentsion" + str;        }    }    class PRogram    {        static void Main(string[] args)        {            string str = "test";            Console.WriteLine(str.ToString()); // 輸出結果為: test,也就說編譯器會優先選用原有類的實例化方法,如果沒找到匹配方法再尋找擴展方法            Console.Read();        }    }

由上述的代碼片段可以知:StringExtentsion類中擴展方法ToString 和 String類的原有的ToString方法 對于客戶端代碼而言,它們的語法表象是

一樣的,但本質上一個是StringExtentsion類的靜態方法,一個是String類的實例化方法。然而編譯運行沒有產生錯誤,更沒有產生警告。所以在

這種情況下很容“埋雷”,一不小心就會中招。有人也許會說:我注意一下不要和.NET類庫的方法重名就可以了。但是你能保證 .NET 6、甚至.NET 10

的方法名和你寫的絕對不重名嗎?所以,擴展方法存在著版本控制的問題

 

三、擴展方法允許在兩個或多個類中共存相同的擴展方法

    public static class StringExtentsion    {        public static bool IsEmpty(this string str)        {            return string.IsNullOrWhiteSpace(str);        }    }    public static class OtherStringExtentsion    {        public static bool IsEmpty(this string str)        {            return string.IsNullOrWhiteSpace(str);        }    }    class Program    {        static void Main(string[] args)        {            string str = null;            //bool result = str.IsEmpty(); // 這種寫法會產生編譯錯誤:不明確的調用,因為它能找到兩個擴展方法            bool result = StringExtentsion.IsEmpty(str); // 必須顯示使用類調用靜態方法            Console.WriteLine(result);            Console.Read();        }    }

  

四、擴展其他類型的方法

擴展方法不僅可以擴展類類型,而且可以擴展接口、枚舉、委托、結構、數組及對應的泛型類型 等類型。

在這里著重說一下擴展接口,任何 “實現了接口的類型對象” 都可以調用接口上的擴展方法。針對這一特點,我們完全可以將實現接口

的共用代碼放進擴展方法里,實現代碼復用。從形式上來看,該特點是 “單繼承 + 接口” 與 “多繼承”的中間產物,已經有了“多繼承”的影子。

 

五、委托與擴展方法

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace MethodDemo{    public static class StringExtentsion    {        public static string ShowString(this string str)        {            return "ShowString:" + str;        }    }    class Program    {        static void Main(string[] args)        {            string str = "meng";            Func<string> fun = str.ShowString;            fun();            Func<string> fun2 = str.ToString;            fun2();            Console.Read();        }    }}

  

如果你已經看過了 .NET 擴展方法 (一) ,也許你能猜到我接下來想說什么了吧。沒錯,看一下IL代碼吧,看看編譯器在背后搞了哪些“怪”。

順便借助這個機會,說幾個IL指令。

 1 .method private hidebysig static void  Main(string[] args) cil managed 2 { 3   .entrypoint 4   // 代碼大小       55 (0x37) 5   .maxstack  2 6  7   // 初始化3個局部變量 8   .locals init ([0] string str, 9            [1] class [mscorlib]System.Func`1<string> fun,10            [2] class [mscorlib]System.Func`1<string> fun2)11   IL_0000:  nop12 13   //將 "meng" 這個字符串對象的引用 入棧14   IL_0001:  ldstr      "meng"15 16   // 將棧頂的值賦值給第0個局部變量(即 str),棧頂值出棧17   IL_0006:  stloc.018 19   // 將第0個局部變量入棧 (即 str 入棧)20   IL_0007:  ldloc.021 22   // 將 MethodDemo.StringExtentsion類的靜態方法ShowString的指針入棧23   IL_0008:  ldftn      string MethodDemo.StringExtentsion::ShowString(string)24 25   // 調用構造函數 new一個 Func<String>類型的委托26   IL_000e:  newobj     instance void class [mscorlib]System.Func`1<string>::.ctor(object,27                                                                                   native int)28   IL_0013:  stloc.129   IL_0014:  ldloc.130 31   // 調用fun對象的Invoke方法32   IL_0015:  callvirt   instance !0 class [mscorlib]System.Func`1<string>::Invoke()33   IL_001a:  pop34   IL_001b:  ldloc.035   IL_001c:  dup36 37   // 將str 對象的實例化方法ToString方法的指針入棧38   IL_001d:  ldvirtftn  instance string [mscorlib]System.Object::ToString()39   IL_0023:  newobj     instance void class [mscorlib]System.Func`1<string>::.ctor(object,40                                                                                   native int)41   IL_0028:  stloc.242   IL_0029:  ldloc.243   IL_002a:  callvirt   instance !0 class [mscorlib]System.Func`1<string>::Invoke()44   IL_002f:  pop45   IL_0030:  call       int32 [mscorlib]System.Console::Read()46   IL_0035:  pop47   IL_0036:  ret48 } // end of method Program::Main

核心的IL指令已經給予了差不多的注釋,根據IL指令可以得出結果:我們又被編譯器“欺騙”了一次,fun對象保存的方法指針是

MethodDemo.StringExtentsion類的靜態方法ShowString的指針。fun2對象保存的方法的指針str對象的ToString方法的指針。

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 偏关县| 团风县| 阜城县| 镇雄县| 保定市| 浪卡子县| 托克逊县| 沙洋县| 怀来县| 介休市| 亳州市| 松阳县| 汾阳市| 巨鹿县| 呈贡县| 桂东县| 婺源县| 高邑县| 南宁市| 浦江县| 华宁县| 若尔盖县| 冀州市| 杭锦后旗| 河西区| 交城县| 青海省| 宜兰县| 保亭| 正宁县| 武山县| 石门县| 商河县| 孙吴县| 深水埗区| 高州市| 西昌市| 三江| 新和县| 延长县| 重庆市|