欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#沉淀之委托的深入講解

 更新時(shí)間:2018年09月23日 12:04:35   作者:東南有大樹(shù)  
如果要給方法傳遞一個(gè)方法參數(shù)時(shí),就可以使用委托。下面這篇文章主要給大家介紹了關(guān)于C#沉淀之委托的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下

什么是委托

要傳遞方法,就必須把方法的細(xì)節(jié)封裝在一鐘新類型的對(duì)象中,即委托。委托是一種特殊類型的對(duì)象,其特殊之處在于,我們以前定義的所有對(duì)象都包含數(shù)據(jù),而委托只包含一個(gè)或多個(gè)方法的地址。

.NET版本中,委托指向方法的地址。在C++中,函數(shù)指針是一個(gè)指向內(nèi)存位置的指針,但它不是類型安全的。開(kāi)發(fā)者無(wú)法判斷這個(gè)指針實(shí)際指向什么,像參數(shù)和返回值等項(xiàng)就更不知道了。

.NET委托是類型安全的類,它定義了返回類型和參數(shù)的類型。委托類不僅包含對(duì)方法的引用,也可以包含對(duì)多個(gè)方法的引用。

可以認(rèn)為委托是持有一個(gè)或多個(gè)方法的對(duì)象。委托可以被執(zhí)行,執(zhí)行委托時(shí)委托會(huì)執(zhí)行它所“持有”的方法

代碼示例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CodeForDelegate
{
 //使用關(guān)鍵字delegate聲明委托類型
 //委托是一種類型,所以它與類屬于同一級(jí)別
 //注意:這里是委托類型,而不是委托對(duì)象
 delegate void MyDel(int value);

 class Program
 {

  void PrintLow(int value)
  {
   Console.WriteLine("{0} - Low Value", value);
  }

  void PrintHigh(int value)
  {
   Console.WriteLine("{0} - High Value", value);
  }

  static void Main(string[] args)
  {
   //實(shí)例化Program類,以訪問(wèn)PrintLow和PrintHigh方法
   Program program = new Program();

   //聲明一個(gè)MyDel類型的委托
   MyDel del;

   //創(chuàng)建隨機(jī)數(shù)
   Random rand = new Random();
   int randomvalue = rand.Next(99);

   //使用三目運(yùn)算符根據(jù)當(dāng)前隨機(jī)數(shù)的值來(lái)創(chuàng)建委托對(duì)象
   del = randomvalue < 50
    ? new MyDel(program.PrintLow)
    : new MyDel(program.PrintHigh);

   //執(zhí)行委托
   del(randomvalue);

   Console.ReadKey();
  }
 }
}

從上例可以看出,使用委托的首先得通過(guò)關(guān)鍵字delegate聲明一個(gè)委托類型,這個(gè)委托類型包括返回值、名稱、簽名;當(dāng)類型聲明好以后,需要通過(guò)new來(lái)創(chuàng)建委托對(duì)象,創(chuàng)建對(duì)象時(shí)的參數(shù)是一個(gè)方法,這個(gè)方法的簽名和返回類型必須與該委托類型定義的簽名一致;調(diào)用委托時(shí),直接通過(guò)實(shí)例化的委托對(duì)象名,并提供參數(shù)即可,然后委托會(huì)執(zhí)行在其所持有的方法

委托與類

委托和類一樣,是一種用戶自定義的類型;不同的是類表示的是數(shù)據(jù)和方法的集合,而委托持有一個(gè)或多個(gè)方法,以及一系列預(yù)定義操作

委托的使用步驟

  • 聲明一個(gè)委托類型
  • 使用該委托類型聲明一個(gè)委托變量
  • 創(chuàng)建委托類型的對(duì)象,把它賦值給委托變量;委托對(duì)象中包括指向某個(gè)方法的引用,此方法和委托類型定義的簽名與返回類型需要一致
  • 增加更多的方法(可選)
  • 像調(diào)用方法一樣調(diào)用委托(委托中的包含的每一個(gè)方法都會(huì)被執(zhí)行)

delegate的原則

delegate相當(dāng)于一個(gè)包含有序方法列表的對(duì)象,這些方法都具有相同的簽名和返回類型

方法的列表稱為調(diào)用列表

委托保存的方法可以來(lái)自任何類或結(jié)構(gòu),只要它們?cè)谝韵聝牲c(diǎn)匹配:

  • 委托的返回類型
  • 委托的簽名(包括ref和out修飾符)

調(diào)用列表中的方法可以是靜態(tài)方法也可以是實(shí)例方法

在調(diào)用委托的時(shí)候,會(huì)調(diào)用列表中的所有方法

聲明委托類型

如下,delegate關(guān)鍵字開(kāi)關(guān),然后是返回類型,再定義名稱與簽名

delegate void MyDel(int vallue);

返回類型與簽名指定了委托接受的方法形式

注意:委托類型是沒(méi)有方法主體的

創(chuàng)建委托對(duì)象

使用new運(yùn)算符創(chuàng)建對(duì)象

MyDel del = new MyDel(object.Func); //object.Func是個(gè)實(shí)例方法
Mydel _del = new MyDel(Object.Func); //Object.Func是個(gè)靜態(tài)方法

使用快捷語(yǔ)法創(chuàng)建對(duì)象

MyDel del = object.Func; //object.Func是個(gè)實(shí)例方法
Mydel _del = Object.Func; //Object.Func是個(gè)靜態(tài)方法

這種語(yǔ)法是能夠工作是因?yàn)樵诜椒Q和其相應(yīng)的委托類型之間存在隱式的轉(zhuǎn)換

創(chuàng)建委托對(duì)象后會(huì)將指定的方法加入到委托的調(diào)用列表中

由于委托是引用類型,可以通過(guò)賦值來(lái)改變包含在委托變量中的引用,如下:

MyDel del;
del = new MyDel(object.FuncA); //創(chuàng)建第一個(gè)對(duì)象
del = new MyDel(object.FuncB); //創(chuàng)建第二個(gè)對(duì)象

由于第二個(gè)對(duì)象也賦值給了變量del,因此del所引用的第一個(gè)對(duì)象將被垃圾回收器回收

組合委托

//創(chuàng)建兩個(gè)委托
MyDel del_A = new MyDel(object.FuncA);
Mydel del_B = new MyDel(object.FuncA);

//組合委托
MyDel del_C = del_A + del_B;

當(dāng)將del_A與del_B通過(guò)+進(jìn)行組合后,會(huì)返回一個(gè)新的委托對(duì)象,該對(duì)象將del_A與del_B中的方法調(diào)用列表組合到新的對(duì)象里,該新對(duì)象賦值給變量del_C,所以執(zhí)行del_C的時(shí)候,會(huì)執(zhí)行del_A與del_B中所保存的方法object.FuncA和object.FuncA

委托添加多個(gè)方法

MyDel del = object.FuncA; //創(chuàng)建并初始化委托對(duì)象
del += object.FuncB; //增加方法
del += object.FuncC; //增加方法

通過(guò)+=符號(hào)為委托對(duì)象添加更多方法,上例中,del對(duì)象不保存了三個(gè)方法,在執(zhí)行del時(shí),這三個(gè)方法會(huì)被依次調(diào)用

注意,在使用+=為委托對(duì)象添加新的方法時(shí),實(shí)際上是創(chuàng)建了一個(gè)新的委托對(duì)象(原對(duì)象的副本)

移除委托方法

del -= object.FuncB; //移除方法
del -= object.FuncC; //移除方法

通過(guò)-=來(lái)將委托調(diào)用列表中已保存的方法,移除動(dòng)作是從調(diào)用列表的最后一個(gè)方法開(kāi)始匹配,一次只會(huì)移除一條匹配的方法,如果調(diào)用列表中不存在該方法,則沒(méi)有任何效果;如果試圖調(diào)用一個(gè)空的委托則會(huì)發(fā)生異常

注意,在使用-=為委托對(duì)象移除方法時(shí),實(shí)際上是創(chuàng)建一個(gè)新的委托對(duì)象(原對(duì)象的副本)

調(diào)用委托

調(diào)用委托就像調(diào)用方法一樣

示例:MyDel類型參考上面的定義

MyDel del = object.FuncA; //創(chuàng)建并初始化委托對(duì)象
del += object.FuncB; //增加方法
del += object.FuncC; //增加方法

//調(diào)用委托 
del(55);

參數(shù)55會(huì)在調(diào)用委托對(duì)象時(shí)依次傳遞給保存的方法

一個(gè)完整的委托示例代碼

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CodeForDelegate
{
 class Program
 {
  //定義委托類型
  delegate void PrintFunction(string txt);

  //測(cè)試類中定義三個(gè)方法
  class Test
  {
   public void PrintA(string txt)
   {
    Console.WriteLine("printA:{0}", txt);
   }

   public void PrintB(string txt)
   {
    Console.WriteLine("printB:{0}", txt);
   }

   public static void PrintC(string txt)
   {
    Console.WriteLine("printC:{0}", txt);
   }
  }
  static void Main(string[] args)
  {
   Test test = new Test();
   PrintFunction pf;

   //實(shí)例化并創(chuàng)建委托對(duì)象
   pf = test.PrintA;

   //為委托對(duì)象增加方法
   pf += test.PrintB;
   pf += Test.PrintC;
   pf += test.PrintA; //添加一個(gè)重復(fù)的方法

   //通過(guò)與null比較,確認(rèn)委托對(duì)象中保存了方法
   if (pf != null)
    pf("Hello");
   else
    Console.WriteLine("pf是個(gè)空委托!");

   Console.ReadKey();
  }
 }
}

調(diào)用帶有返回值的委托

如何委托有返回值,并且調(diào)用列表中有一個(gè)以上的方法,那么將使用最后一個(gè)方法的返回值,之前方法的返回值被忽略

示例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CodeForDelegate
{
 class Program
 {
  //定義委托類型
  delegate int DelFunction();

  //測(cè)試類中定義三個(gè)方法
  class Test
  {
   int IntValue = 0;
   
   public int FuncA()
   {
    return IntValue += 1;
   }

   public int FuncB()
   {
    return IntValue += 10;
   }
  }
  static void Main(string[] args)
  {
   Test test = new Test();
   DelFunction df;

   df = test.FuncA;
   df += test.FuncB;

   //最終返回值的是11
   if (df != null)
    Console.WriteLine("返回值:"+df());
   else
    Console.WriteLine("pf是個(gè)空委托!");

   Console.ReadKey();
  }
 }
}

具有引用參數(shù)的委托

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CodeForDelegate
{
 //定義委托類型
 delegate void MyDel(ref int x);
 class Program
 {

  static void Add1(ref int x) { x += 1; }
  static void Add2(ref int x) { x += 2; }

  static void Main(string[] args)
  {
   Program program = new Program();

   MyDel del = Add1;
   del += Add2;

   //ref會(huì)將x當(dāng)作引用值傳遞給委托方法
   int x = 5;
   del(ref x);

   Console.ReadKey();
  }
 }
}

在調(diào)用Add1方法時(shí),x = 5+1,再調(diào)用Add2方法時(shí),不是x = 5+2而是x = 6 +2

參考:ref按引用傳遞參數(shù)

在方法的參數(shù)列表中使用 ref 關(guān)鍵字時(shí),它指示參數(shù)按引用傳遞,而非按值傳遞。 按引用傳遞的效果是,對(duì)所調(diào)用方法中參數(shù)進(jìn)行的任何更改都反映在調(diào)用方法中。 例如,如果調(diào)用方傳遞本地變量表達(dá)式或數(shù)組元素訪問(wèn)表達(dá)式,所調(diào)用方法會(huì)替換 ref 參數(shù)引用的對(duì)象,然后,當(dāng)該方法返回時(shí),調(diào)用方的本地變量或數(shù)組元素將開(kāi)始引用新對(duì)象

匿名方法

匿名方法是在初始化委托時(shí)內(nèi)聯(lián)聲明的方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CodeForDelegate
{
 //定義委托類型
 delegate void MyDel(ref int x);
 class Program
 {

  static void Add1(ref int x) { x += 1; }
  static void Add2(ref int x) { x += 2; }

  static void Main(string[] args)
  {
   Program program = new Program();
   
   //采用匿名方法形式代替具名方法
   MyDel del = delegate(ref int y) { y += 3; };
   del += Add1;
   del += Add2;

   //ref會(huì)將x當(dāng)作引用值傳遞給委托方法
   int x = 5;
   del(ref x);

   Console.ReadKey();
  }
 }
}

在聲明委托變量時(shí)作為初始化表達(dá)式,或在為委托增加事件時(shí)使用

語(yǔ)法解析

以關(guān)鍵字delegate開(kāi)頭;后跟小括號(hào)提供參數(shù);再后跟{}作為語(yǔ)句塊

delegate (Parameters) {ImplementationCode}

  • 匿名方法不會(huì)顯示的聲明返回類型delegate (int x) { return x;}即為返回一個(gè)int類型的值
  • 參數(shù)的數(shù)量、位置、類型、修飾符必須與委托相匹配
  • 可以通過(guò)省略圓括號(hào)或使圓括號(hào)為空來(lái)簡(jiǎn)化匿名方法的參數(shù)列表,前提是參數(shù)是不包含out參數(shù),方法體中不使用任何參數(shù)

示例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CodeForDelegate
{
 //定義委托類型
 delegate void MyDel(ref int x);
 class Program
 {

  static void Add1(ref int x) { x += 1; }
  static void Add2(ref int x) { x += 2; }

  static void Main(string[] args)
  {
   Program program = new Program();
   
   //采用匿名方法形式代替具名方法
   MyDel del = delegate(ref int y) { y += 3; };
   del += Add1;
   del += Add2;
   
   //匿名方法未使用任何參數(shù),簡(jiǎn)化形式
   del += delegate{int z = 10;};

   //ref會(huì)將x當(dāng)作引用值傳遞給委托方法
   int x = 5;
   del(ref x);

   Console.ReadKey();
  }
 }
}

如果定義一個(gè)帶有params形式的參數(shù),在使用匿名方法的時(shí)候可以省略params關(guān)鍵字以簡(jiǎn)化代碼

示例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CodeForDelegate
{
 //定義一個(gè)帶有params形式參數(shù)的委托類型
 delegate void DelFunction(int x, params int[] z);
 class Program
 {
  static void Main(string[] args)
  {
   Program program = new Program();
   
   // 關(guān)鍵字params被忽略(省略關(guān)鍵字以簡(jiǎn)化)
   DelFunction df = delegate(int x, int[] y) { ... };

   Console.ReadKey();
  }
 }
}

Lambda表達(dá)式

Lambda可以簡(jiǎn)化匿名方法,語(yǔ)法形式如下:

(參數(shù)) => {語(yǔ)句塊} // => 讀作 gose to

參數(shù)中的類型可以省略
如果只有一個(gè)參數(shù),圓括號(hào)可以省略
如果沒(méi)有參數(shù),圓括號(hào)不可以省略
語(yǔ)句塊如果只有一行代碼,花括號(hào)可以省略

示例:

MyDel del = delegate(int y) { return y += 3; }; //匿名方法
MyDel del1 = (int y) => {return y += 3;} // Lambda表達(dá)式
MyDel del2 = (y) => {return y += 3;} // 省略參數(shù)類型
MyDel del3 = y => y += 3; // 省略圓括號(hào)和花括號(hào),雖然沒(méi)有return,但仍會(huì)返回y的值

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • 淺解關(guān)于C#多線程的介紹

    淺解關(guān)于C#多線程的介紹

    本篇文章小編將為大家介紹,淺解關(guān)于C#的多線程,有需要的朋友可以參考一下
    2013-04-04
  • C#+無(wú)unsafe的非托管大數(shù)組示例詳解(large unmanaged array in c# without ‘unsafe’ keyword)

    C#+無(wú)unsafe的非托管大數(shù)組示例詳解(large unmanaged array in c# without ‘u

    這篇文章主要給大家介紹了關(guān)于C#+無(wú)unsafe的非托管大數(shù)組(large unmanaged array in c# without 'unsafe' keyword)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • C#控制臺(tái)帶參數(shù)程序源碼編寫(xiě)實(shí)例講解

    C#控制臺(tái)帶參數(shù)程序源碼編寫(xiě)實(shí)例講解

    像ipconfig /all 這樣的CMD命令想必大家都知道,但是很多童鞋可能不知道怎么寫(xiě)這樣的控制臺(tái)帶參數(shù)的程序,需要的朋友可以了解下
    2012-12-12
  • 深入理解C#中的Delegate

    深入理解C#中的Delegate

    委托是一種安全地封裝方法的類型,它與 C 和 C++ 中的函數(shù)指針類似。與 C 中的函數(shù)指針不同,委托是面向?qū)ο蟮?、類型安全的和保險(xiǎn)的。委托的類型由委托的名稱定義
    2016-07-07
  • Visual Studio 2019 清理空行問(wèn)題(非正則表達(dá)式)

    Visual Studio 2019 清理空行問(wèn)題(非正則表達(dá)式)

    這篇文章主要介紹了Visual Studio 2019 清理空行問(wèn)題(非正則表達(dá)式),本文通過(guò)實(shí)例截圖給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-04-04
  • C#中的9個(gè)“黑魔法”

    C#中的9個(gè)“黑魔法”

    這篇文章主要介紹了C#中的9個(gè)“黑魔法”與“騷操作”,本文通過(guò)實(shí)例代碼給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-04-04
  • C#使用NPOI實(shí)現(xiàn)Excel和DataTable的互轉(zhuǎn)

    C#使用NPOI實(shí)現(xiàn)Excel和DataTable的互轉(zhuǎn)

    這篇文章主要為大家詳細(xì)介紹了C#使用NPOI實(shí)現(xiàn)Excel和DataTable的互轉(zhuǎn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C#實(shí)現(xiàn)給圖片加水印的方法

    C#實(shí)現(xiàn)給圖片加水印的方法

    這篇文章主要介紹了C#實(shí)現(xiàn)給圖片加水印的方法,結(jié)合完整實(shí)例形式分析了C#常見(jiàn)的圖片水印操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2016-02-02
  • C#之Windows自帶打印功能的實(shí)現(xiàn)

    C#之Windows自帶打印功能的實(shí)現(xiàn)

    這篇文章主要介紹了C#之Windows自帶打印功能的實(shí)現(xiàn)方式,具有很好的價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • C#中感嘆號(hào)(!) 的作用總結(jié)

    C#中感嘆號(hào)(!) 的作用總結(jié)

    這篇文章主要給大家總結(jié)介紹了C#中感嘆號(hào)(!) 的作用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12

最新評(píng)論