最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解C#擴展方法原理及其使用

 更新時間:2020年06月23日 16:50:58   作者:艾心❤  
這篇文章主要介紹了C#擴展方法原理及其使用的的相關(guān)資料,文中代碼非常細致,幫助大家更好的理解和學習,感興趣的朋友可以了解下

1、寫在前面

今天群里一個小伙伴問了這樣一個問題,擴展方法與實例方法的執(zhí)行順序是什么樣子的,誰先誰后(這個問題會在文章結(jié)尾回答)。所以寫了這邊文章,力圖從原理角度解釋擴展方法及其使用。

以下為主要內(nèi)容:

  • 什么是擴展方法
  • 擴展方法原理及自定義擴展方法
  • 擴展方法的使用及其注意事項

2、什么是擴展方法

      一般而言,擴展方法為現(xiàn)有類型添加新的方法(從面向?qū)ο蟮慕嵌葋碚f,是為現(xiàn)有對象添加新的行為)而無需修改原有類型,這是一種無侵入而且非常安全的方式。擴展方法是靜態(tài)的,它的使用和其他實例方法幾乎沒有什么區(qū)別。常見的擴展方法有Linq擴展、有IEnumerable擴展等。

     先讓我們來感受一下.NET中自帶的擴展方法,其中OrderBy和Aggregate都是系統(tǒng)自帶的擴展方法

using System;
using System.Collections.Generic;
using System.Linq;

namespace Test
{
 class Program
 {
  static void Main(string[] args)
  {
   List<int> lst = new List<int> { 2, 1, 4, 3 };

   string result = lst.OrderBy(p => p).Aggregate(string.Empty, (next, p) => next += p + ",");

   Console.WriteLine(result);

   Console.ReadLine();
  }
 }
}

是不是感覺擴展方法很優(yōu)美,使用起來和實例方法幾乎沒有區(qū)別。不得不說.NET在這方面做得很精致,很讓人欽佩,那么接下來我們來看看擴展方法的原理

3、擴展方法原理及自定義擴展方法

首先我們,先看看如何自定義擴展方法

using System;
using TestExtension;

namespace Test
{
 class Program
 {
  static void Main(string[] args)
  {
   Console.WriteLine("2".ToInt32());

   Console.ReadLine();
  }
 }
}

namespace TestExtension
{
 public static class StringExtension
 {
  public static int ToInt32(this string str)
  {
   if (int.TryParse(str, out int result))
   {
    return result;
   }

   throw new ArgumentException("無法轉(zhuǎn)換為Int32類型");
  }
 }
}
  • 必須是靜態(tài)類,擴展方法也為靜態(tài)方法
  • 此方法的第一個參數(shù)指定方法所操作的類型;此參數(shù)前面必須加上 this 修飾符
  • 在調(diào)用代碼中,如何不再同一個命名空間,需要添加 using 指令,導入需要調(diào)用的擴展方法所在的命名空間
  • 需要注意的是,第一個this標記的參數(shù)并非是實參,而是標識該擴展所指定的類型,調(diào)用的時候只需要提供this后的形參即可

接下來我們來探究一下擴展方法反編譯后的效果:

這是StringExtension編譯后的代碼,可以看到擴展方法在編譯后被標記了ExtensionAttribute這個特性,也就是說擴展方法在編譯期就已經(jīng)被綁定成擴展方法了

.class public auto ansi abstract sealed beforefieldinit TestExtension.StringExtension
 extends [System.Runtime]System.Object
{
 .custom instance void 
[System.Runtime]System.Runtime.CompilerServices.ExtensionAttribute
::.ctor() = (
  01 00 00 00
 )
 // Methods
 .method public hidebysig static 
  int32 ToInt32 (
   string str
  ) cil managed 
 {
  .custom instance void 
[System.Runtime]System.Runtime.CompilerServices.ExtensionAttribute
::.ctor() = (
   01 00 00 00
  )
  // Method begins at RVA 0x2050
  // Code size 31 (0x1f)
  .maxstack 2
  .locals init (
   [0] int32,
   [1] bool,
   [2] int32
  )

  IL_0000: nop
  IL_0001: ldarg.0
  IL_0002: ldloca.s 0
  IL_0004: call bool [System.Runtime]System.Int32::TryParse(string, int32&)
  IL_0009: stloc.1
  IL_000a: ldloc.1
  IL_000b: brfalse.s IL_0012

  IL_000d: nop
  IL_000e: ldloc.0
  IL_000f: stloc.2
  IL_0010: br.s IL_001d

  IL_0012: ldstr "無法轉(zhuǎn)換為Int32類型"
  IL_0017: newobj instance void [System.Runtime]System.ArgumentException::.ctor(string)
  IL_001c: throw

  IL_001d: ldloc.2
  IL_001e: ret
 } // end of method StringExtension::ToInt32

} // end of class TestExtension.StringExtension

我們看一下調(diào)用后的效果,和直接調(diào)用靜態(tài)方法一樣TestExtension.StringExtension::ToInt32(string) ,至此,我們已經(jīng)知道了擴展方法的使用了,編譯器綁定,底層調(diào)用和靜態(tài)調(diào)用一直,這也解釋了一個問題,就是當類型為空的時候,為什么調(diào)用擴展方法了

.namespace Test
{
 .class private auto ansi beforefieldinit Test.Program
  extends [System.Runtime]System.Object
 {
  // Methods
  .method private hidebysig static 
   void Main (
    string[] args
   ) cil managed 
  {
   // Method begins at RVA 0x207b
   // Code size 24 (0x18)
   .maxstack 8
   .entrypoint

   IL_0000: nop
   IL_0001: ldstr "2"
   IL_0006: call int32 TestExtension.StringExtension::ToInt32(string)
   IL_000b: call void [System.Console]System.Console::WriteLine(int32)
   IL_0010: nop
   IL_0011: call string [System.Console]System.Console::ReadLine()
   IL_0016: pop
   IL_0017: ret
  } // end of method Program::Main

  .method public hidebysig specialname rtspecialname 
   instance void .ctor () cil managed 
  {
   // Method begins at RVA 0x2094
   // Code size 8 (0x8)
   .maxstack 8

   IL_0000: ldarg.0
   IL_0001: call instance void [System.Runtime]System.Object::.ctor()
   IL_0006: nop
   IL_0007: ret
  } // end of method Program::.ctor

 } // end of class Test.Program

}

4、擴展方法的使用及其注意事項

擴展方法雖然很好用,但是如果我們擴展的對象發(fā)生了版本迭代,則會增加擴展方法失效的風險。

一下是在使用擴展方法時需要注意的地方

  • 擴展方法與該類型中定義的方法具有相同的簽名,編譯器總是綁定到該實例方法,也就是擴展方法永遠不會被調(diào)用,這也就回答了題目剛開始所說的問題。同時這個地方應(yīng)該是考慮到了程序安全的問題,不然很容易出現(xiàn)代碼注入問題。
  • 當出現(xiàn)命名空間不同時,則需要使用using導入命名空間
  • 同時擴展方法可以被修飾為internal,public,但需要類和擴展方法保持同樣的修飾標識

以上就是詳解C#擴展方法原理及其使用的詳細內(nèi)容,更多關(guān)于c# 擴展方法的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • c#索引器詳解示例

    c#索引器詳解示例

    索引器是一種特殊的類成員,它能夠讓對象以類似數(shù)組的方式來存取,使程序看起來更為直觀,更容易編寫。
    2014-04-04
  • C# 改變無邊框窗體尺寸大小的方法

    C# 改變無邊框窗體尺寸大小的方法

    這篇文章介紹了C# 改變無邊框窗體尺寸大小的方法,有需要的朋友可以參考一下
    2013-10-10
  • C# 開發(fā)step步驟條控件詳解

    C# 開發(fā)step步驟條控件詳解

    本篇文章主要介紹了用C#來實現(xiàn)一個step控件的方法步驟,具有很好的參考價值。下面跟著小編一起來看下吧
    2017-03-03
  • 基于C#實現(xiàn)一個溫濕度監(jiān)測小工具

    基于C#實現(xiàn)一個溫濕度監(jiān)測小工具

    這篇文章主要為大家詳細介紹了如何基于C#實現(xiàn)一個溫濕度監(jiān)測小工具,文中的示例代碼講解詳細,具有一定的借鑒價值,需要的可以參考一下
    2023-01-01
  • C#4.0新特性之協(xié)變與逆變實例分析

    C#4.0新特性之協(xié)變與逆變實例分析

    這篇文章主要介紹了C#4.0新特性的協(xié)變與逆變,是比較實用的一個新功能,需要的朋友可以參考下
    2014-09-09
  • C#.Net基于正則表達式抓取百度百家文章列表的方法示例

    C#.Net基于正則表達式抓取百度百家文章列表的方法示例

    這篇文章主要介紹了C#.Net基于正則表達式抓取百度百家文章列表的方法,結(jié)合實例形式分析了C#獲取百度百家文章內(nèi)容及使用正則表達式匹配標題、內(nèi)容、地址等相關(guān)操作技巧,需要的朋友可以參考下
    2017-08-08
  • C#編寫一個網(wǎng)游客戶端的完整步驟

    C#編寫一個網(wǎng)游客戶端的完整步驟

    這篇文章主要給大家介紹了關(guān)于C#編寫一個網(wǎng)游客戶端的相關(guān)資料,文中通過示例代碼以及圖文介紹的非常詳細,對大家學習或者使用C#具有一定的參考學習價值,需要的朋友可以參考下
    2021-11-11
  • C#實現(xiàn)Access通用訪問類OleDbHelper完整實例

    C#實現(xiàn)Access通用訪問類OleDbHelper完整實例

    這篇文章主要介紹了C#實現(xiàn)Access通用訪問類OleDbHelper,結(jié)合完整實例形式分析了C#針對access數(shù)據(jù)庫的連接、查詢、遍歷、分頁顯示等相關(guān)操作技巧,需要的朋友可以參考下
    2017-02-02
  • C#實現(xiàn)控制攝像頭的類

    C#實現(xiàn)控制攝像頭的類

    這篇文章主要介紹了C#實現(xiàn)控制攝像頭的類,涉及C#操作攝像頭的初始化、抓圖、錄像等功能,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-09-09
  • js驗證電話號碼手機號碼的正則表達式

    js驗證電話號碼手機號碼的正則表達式

    本篇文章主要是對js驗證電話號碼手機號碼的正則表達式進行了介紹。需要的朋友可以過來參考下,希望對大家有所幫助
    2014-01-01

最新評論

泽州县| 浑源县| 平山县| 大连市| 炉霍县| 东至县| 东平县| 固始县| 饶平县| 诸暨市| 隆子县| 库尔勒市| 海晏县| 临沂市| 阿荣旗| 交城县| 蓬溪县| 子洲县| 阿克苏市| 昭苏县| 克拉玛依市| 卓资县| 合江县| 民权县| 深水埗区| 泾阳县| 汨罗市| 平阳县| 宣武区| 合江县| 蒲城县| 临武县| 乌兰浩特市| 桓仁| 金堂县| 东台市| 泸西县| 丹阳市| 鄱阳县| 桃园县| 聂荣县|