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

C#中的delegate委托類型基本學(xué)習(xí)教程

 更新時(shí)間:2016年01月31日 16:15:09   投稿:goldensun  
這篇文章主要介紹了C#中的delegate委托類型基本學(xué)習(xí)教程,委托是C#語(yǔ)言所具有的一個(gè)重要特性,需要的朋友可以參考下

委托
delegate 是表示對(duì)具有特定參數(shù)列表和返回類型的方法的引用的類型。在實(shí)例化委托時(shí),你可以將其實(shí)例與任何具有兼容簽名和返回類型的方法相關(guān)聯(lián)。你可以通過(guò)委托實(shí)例調(diào)用方法。
委托用于將方法作為參數(shù)傳遞給其他方法。事件處理程序就是通過(guò)委托調(diào)用的方法。你可以創(chuàng)建一個(gè)自定義方法,當(dāng)發(fā)生特定事件時(shí),某個(gè)類(如 Windows 控件)就可以調(diào)用你的方法。下面的示例演示了一個(gè)委托聲明:

public delegate int PerformCalculation(int x, int y);

可將任何可訪問(wèn)類或結(jié)構(gòu)中與委托類型匹配的任何方法分配給委托。該方法可以是靜態(tài)方法,也可以是實(shí)例方法。這樣便能通過(guò)編程方式來(lái)更改方法調(diào)用,還可以向現(xiàn)有類中插入新代碼。
注意:在方法重載的上下文中,方法的簽名不包括返回值。但在委托的上下文中,簽名包括返回值。換句話說(shuō),方法和委托必須具有相同的返回類型。
將方法作為參數(shù)進(jìn)行引用的能力使委托成為定義回調(diào)方法的理想選擇。例如,對(duì)比較兩個(gè)對(duì)象的方法的引用可以作為參數(shù)傳遞到排序算法中。由于比較代碼在一個(gè)單獨(dú)的過(guò)程中,因此可通過(guò)更常見的方式編寫排序算法。
委托概述
委托具有以下屬性:

  1. 委托類似于 C++ 函數(shù)指針,但它們是類型安全的。
  2. 委托允許將方法作為參數(shù)進(jìn)行傳遞。
  3. 委托可用于定義回調(diào)方法。
  4. 委托可以鏈接在一起;例如,可以對(duì)一個(gè)事件調(diào)用多個(gè)方法。
  5. 方法不必與委托類型完全匹配。
  6. C# 2.0 版引入了匿名方法的概念,此類方法允許將代碼塊作為參數(shù)傳遞來(lái)代替單獨(dú)定義的方法。C# 3.0 引入了 Lambda 表達(dá)式,利用它們可以更簡(jiǎn)練地編寫內(nèi)聯(lián)代碼塊。匿名方法和 Lambda 表達(dá)式(在某些上下文中)都可編譯為委托類型。這些功能現(xiàn)在統(tǒng)稱為匿名函數(shù)。

使用委托

委托是安全封裝方法的類型,類似于 C 和 C++ 中的函數(shù)指針。與 C 函數(shù)指針不同的是,委托是面向?qū)ο蟮摹㈩愋桶踩暮涂煽康?。委托的類型由委托的名稱確定。以下示例聲明名為 Del 的委托,該委托可以封裝采用字符串作為參數(shù)并返回 void 的方法:

public delegate void Del(string message);

委托對(duì)象通常通過(guò)提供委托將封裝的方法的名稱或使用匿名方法構(gòu)造。對(duì)委托進(jìn)行實(shí)例化后,委托會(huì)將對(duì)其進(jìn)行的方法調(diào)用傳遞到該方法。調(diào)用方傳遞到委托的參數(shù)將傳遞到該方法,并且委托會(huì)將方法的返回值(如果有)返回到調(diào)用方。這被稱為調(diào)用委托。實(shí)例化的委托可以按封裝的方法本身進(jìn)行調(diào)用。例如:

 // Create a method for a delegate.
public static void DelegateMethod(string message)
{
  System.Console.WriteLine(message);
}


 // Instantiate the delegate.
Del handler = DelegateMethod;

// Call the delegate.
handler("Hello World");


委托類型派生自 .NET Framework 中的 Delegate 類。委托類型是封裝的,它們不能派生出其他類,也不能從 Delegate 派生出自定義類。由于實(shí)例化的委托是一個(gè)對(duì)象,因此可以作為參數(shù)傳遞或分配給一個(gè)屬性。這允許方法作為參數(shù)接受委托并在稍后調(diào)用委托。這被稱為異步回調(diào),是在長(zhǎng)進(jìn)程完成時(shí)通知調(diào)用方的常用方法。當(dāng)以這種方式使用委托時(shí),使用委托的代碼不需要知道要使用的實(shí)現(xiàn)方法。功能類似于封裝接口提供的功能。
回調(diào)的另一個(gè)常見用途是定義自定義比較方法并將該委托傳遞到短方法。它允許調(diào)用方的代碼成為排序算法的一部分。以下示例方法使用 Del 類型作為參數(shù):

public void MethodWithCallback(int param1, int param2, Del callback)
{
  callback("The number is: " + (param1 + param2).ToString());
}

然后,你可以將上面創(chuàng)建的委托傳遞到該方法:

MethodWithCallback(1, 2, handler);

并將以下輸出接收到控制臺(tái):

The number is: 3

以抽象方式使用委托時(shí),MethodWithCallback 不需要直接調(diào)用控制臺(tái),記住,其不必設(shè)計(jì)為具有控制臺(tái)。 MethodWithCallback 的作用是簡(jiǎn)單準(zhǔn)備字符串并將字符串傳遞到其他方法。由于委托的方法可以使用任意數(shù)量的參數(shù),此功能特別強(qiáng)大。
當(dāng)委托構(gòu)造為封裝實(shí)例方法時(shí),委托將同時(shí)引用實(shí)例和方法。委托不知道除其所封裝方法以外的實(shí)例類型,因此委托可以引用任何類型的對(duì)象,只要該對(duì)象上有與委托簽名匹配的方法。當(dāng)委托構(gòu)造為封裝靜態(tài)方法時(shí),委托僅引用方法。請(qǐng)考慮以下聲明:

public class MethodClass
{
  public void Method1(string message) { }
  public void Method2(string message) { }
}

加上之前顯示的靜態(tài) DelegateMethod,我們現(xiàn)在已有三個(gè) Del 實(shí)例可以封裝的方法。
調(diào)用時(shí),委托可以調(diào)用多個(gè)方法。這被稱為多播。若要向委托的方法列表(調(diào)用列表)添加其他方法,只需使用加法運(yùn)算符或加法賦值運(yùn)算符(“+”或“+=”)添加兩個(gè)委托。例如:

MethodClass obj = new MethodClass();
Del d1 = obj.Method1;
Del d2 = obj.Method2;
Del d3 = DelegateMethod;

//Both types of assignment are valid.
Del allMethodsDelegate = d1 + d2;
allMethodsDelegate += d3;

此時(shí),allMethodsDelegate 的調(diào)用列表中包含三個(gè)方法,分別為 Method1、Method2 和 DelegateMethod。原有的三個(gè)委托(d1、d2 和 d3)保持不變。調(diào)用 allMethodsDelegate 時(shí),將按順序調(diào)用所有三個(gè)方法。如果委托使用引用參數(shù),引用將按相反的順序傳遞到所有這三個(gè)方法,并且一種方法進(jìn)行的任何更改都將在另一種方法上見到。當(dāng)方法引發(fā)未在方法內(nèi)捕獲到的異常時(shí),該異常將傳遞到委托的調(diào)用方,并且不會(huì)調(diào)用調(diào)用列表中的后續(xù)方法。如果委托具有返回值和/或輸出參數(shù),它將返回上次調(diào)用方法的返回值和參數(shù)。若要?jiǎng)h除調(diào)用列表中的方法,請(qǐng)使用減法運(yùn)算符或減法賦值運(yùn)算符(“+”或“+=”)。例如:

//remove Method1
allMethodsDelegate -= d1;

// copy AllMethodsDelegate while removing d2
Del oneMethodDelegate = allMethodsDelegate - d2;

由于委托類型派生自 System.Delegate,因此可以在委托上調(diào)用該類定義的方法和屬性。例如,若要查詢委托調(diào)用列表中方法的數(shù)量,你可以編寫:

int invocationCount = d1.GetInvocationList().GetLength(0);

調(diào)用列表中具有多個(gè)方法的委托派生自 MulticastDelegate,該類屬于 System.Delegate 的子類。由于這兩個(gè)類都支持 GetInvocationList,因此在其他情況下,上述代碼也將產(chǎn)生作用。
多播委托廣泛用于事件處理中。事件源對(duì)象將事件通知發(fā)送到已注冊(cè)接收該事件的接收方對(duì)象。若要注冊(cè)一個(gè)事件,接收方需要?jiǎng)?chuàng)建用于處理該事件的方法,然后為該方法創(chuàng)建委托并將委托傳遞到事件源。事件發(fā)生時(shí),源調(diào)用委托。然后,委托將對(duì)接收方調(diào)用事件處理方法,從而提供事件數(shù)據(jù)。給定事件的委托類型由事件源確定。有關(guān)詳細(xì)信息,請(qǐng)參閱事件(C# 編程指南)。
在編譯時(shí)比較分配的兩個(gè)不同類型的委托將導(dǎo)致編譯錯(cuò)誤。如果委托實(shí)例是靜態(tài)的 System.Delegate 類型,則允許比較,但在運(yùn)行時(shí)將返回 false。例如:

delegate void Delegate1();
delegate void Delegate2();

static void method(Delegate1 d, Delegate2 e, System.Delegate f)
{
  // Compile-time error.
  //Console.WriteLine(d == e);

  // OK at compile-time. False if the run-time type of f 
  // is not the same as that of d.
  System.Console.WriteLine(d == f);
}


帶有命名方法的委托與帶有匿名方法的委托

委托可以與命名方法關(guān)聯(lián)。使用命名方法對(duì)委托進(jìn)行實(shí)例化時(shí),該方法將作為參數(shù)傳遞,例如:

// Declare a delegate:
delegate void Del(int x);

// Define a named method:
void DoWork(int k) { /* ... */ }

// Instantiate the delegate using the method as a parameter:
Del d = obj.DoWork;

這被稱為使用命名的方法。使用命名方法構(gòu)造的委托可以封裝靜態(tài)方法或?qū)嵗椒?。在早期版本?C# 中,命名方法是對(duì)委托進(jìn)行實(shí)例化的唯一方式。但是,在不希望付出創(chuàng)建新方法的系統(tǒng)開銷時(shí),C# 使您可以對(duì)委托進(jìn)行實(shí)例化,并立即指定委托在被調(diào)用時(shí)將處理的代碼塊。代碼塊可以包含 lambda 表達(dá)式或匿名方法。

備注:作為委托參數(shù)傳遞的方法必須與委托聲明具有相同的簽名。
委托實(shí)例可以封裝靜態(tài)或?qū)嵗椒ā?br /> 盡管委托可以使用 out 參數(shù),但建議您不要將其用于多路廣播事件委托,因?yàn)槟鸁o(wú)法知道哪個(gè)委托將被調(diào)用。
示例 1
以下是聲明及使用委托的一個(gè)簡(jiǎn)單示例。注意,委托 Del 和關(guān)聯(lián)的方法 MultiplyNumbers 具有相同的簽名

// Declare a delegate
delegate void Del(int i, double j);

class MathClass
{
  static void Main()
  {
    MathClass m = new MathClass();

    // Delegate instantiation using "MultiplyNumbers"
    Del d = m.MultiplyNumbers;

    // Invoke the delegate object.
    System.Console.WriteLine("Invoking the delegate using 'MultiplyNumbers':");
    for (int i = 1; i <= 5; i++)
    {
      d(i, 2);
    }

    // Keep the console window open in debug mode.
    System.Console.WriteLine("Press any key to exit.");
    System.Console.ReadKey();
  }

  // Declare the associated method.
  void MultiplyNumbers(int m, double n)
  {
    System.Console.Write(m * n + " ");
  }
}

輸出:

  Invoking the delegate using 'MultiplyNumbers':
  2 4 6 8 10

示例 2
在下面的示例中,一個(gè)委托被同時(shí)映射到靜態(tài)方法和實(shí)例方法,并分別返回特定的信息。

// Declare a delegate
delegate void Del();

class SampleClass
{
  public void InstanceMethod()
  {
    System.Console.WriteLine("A message from the instance method.");
  }

  static public void StaticMethod()
  {
    System.Console.WriteLine("A message from the static method.");
  }
}

class TestSampleClass
{
  static void Main()
  {
    SampleClass sc = new SampleClass();

    // Map the delegate to the instance method:
    Del d = sc.InstanceMethod;
    d();

    // Map to the static method:
    d = SampleClass.StaticMethod;
    d();
  }
}

輸出:

  A message from the instance method.
  A message from the static method.

相關(guān)文章

最新評(píng)論