C#中的delegate拜托類型根本進修教程。本站提示廣大學習愛好者:(C#中的delegate拜托類型根本進修教程)文章只能為提供參考,不一定能成為您想要的結果。以下是C#中的delegate拜托類型根本進修教程正文
拜托
delegate 是表現對具有特定參數列表和前往類型的辦法的援用的類型。在實例化拜托時,你可以將其實例與任何具有兼容簽名和前往類型的辦法相干聯。你可以經由過程拜托實例挪用辦法。
拜托用於將辦法作為參數傳遞給其他辦法。事宜處置法式就是經由過程拜托挪用的辦法。你可以創立一個自界說辦法,當產生特定事宜時,某個類(如 Windows 控件)便可以挪用你的辦法。上面的示例演示了一個拜托聲明:
public delegate int PerformCalculation(int x, int y);
可將任何可拜訪類或構造中與拜托類型婚配的任何辦法分派給拜托。該辦法可所以靜態辦法,也能夠是實例辦法。如許便能經由過程編程方法來更改辦法挪用,還可以向現有類中拔出新代碼。
留意:在辦法重載的高低文中,辦法的簽名不包含前往值。但在拜托的高低文中,簽名包含前往值。換句話說,辦法和拜托必需具有雷同的前往類型。
將辦法作為參數停止援用的才能使拜托成為界說回調辦法的幻想選擇。例如,比較較兩個對象的辦法的援用可以作為參數傳遞到排序算法中。因為比擬代碼在一個零丁的進程中,是以可經由過程更罕見的方法編寫排序算法。
拜托概述
拜托具有以部屬性:
應用拜托
拜托是平安封裝辦法的類型,相似於 C 和 C++ 中的函數指針。與 C 函數指針分歧的是,拜托是面向對象的、類型平安的和靠得住的。拜托的類型由拜托的稱號肯定。以下示例聲明名為 Del 的拜托,該拜托可以封裝采取字符串作為參數並前往 void 的辦法:
public delegate void Del(string message);
拜托對象平日經由過程供給拜托將封裝的辦法的稱號或應用匿名辦法結構。對拜托停止實例化後,拜托會將對其停止的辦法挪用傳遞到該辦法。挪用方傳遞到拜托的參數將傳遞到該辦法,而且拜托會將辦法的前往值(假如有)前往到挪用方。這被稱為挪用拜托。實例化的拜托可以按封裝的辦法自己停止挪用。例如:
// 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 派生出自界說類。因為實例化的拜托是一個對象,是以可以作為參數傳遞或分派給一個屬性。這許可辦法作為參數接收拜托並在稍後挪用拜托。這被稱為異步回調,是在出息程完成時告訴挪用方的經常使用辦法。當以這類方法應用拜托時,應用拜托的代碼不須要曉得要應用的完成辦法。功效相似於封裝接口供給的功效。
回調的另外一個罕見用處是界說自界說比擬辦法並將該拜托傳遞到短辦法。它許可挪用方的代碼成為排序算法的一部門。以下示例辦法應用 Del 類型作為參數:
public void MethodWithCallback(int param1, int param2, Del callback) { callback("The number is: " + (param1 + param2).ToString()); }
然後,你可以將下面創立的拜托傳遞到該辦法:
MethodWithCallback(1, 2, handler);
並將以下輸入吸收到掌握台:
The number is: 3
以籠統方法應用拜托時,MethodWithCallback 不須要直接挪用掌握台,記住,其不用設計為具有掌握台。 MethodWithCallback 的感化是簡略預備字符串並將字符串傳遞到其他辦法。因為拜托的辦法可使用隨意率性數目的參數,此功效特殊壯大。
當拜托結構為封裝實例辦法時,拜托將同時援用實例和辦法。拜托不曉得除其所封裝辦法之外的實例類型,是以拜托可以援用任何類型的對象,只需該對象上有與拜托簽名婚配的辦法。當拜托結構為封裝靜態辦法時,拜托僅援用辦法。請斟酌以下聲明:
public class MethodClass { public void Method1(string message) { } public void Method2(string message) { } }
加上之前顯示的靜態 DelegateMethod,我們如今已有三個 Del 實例可以封裝的辦法。
挪用時,拜托可以挪用多個辦法。這被稱為多播。若要向拜托的辦法列表(挪用列表)添加其他辦法,只需應用加法運算符或加法賦值運算符(“+”或“+=”)添加兩個拜托。例如:
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;
此時,allMethodsDelegate 的挪用列表中包括三個辦法,分離為 Method1、Method2 和 DelegateMethod。原本的三個拜托(d1、d2 和 d3)堅持不變。挪用 allMethodsDelegate 時,將按次序挪用一切三個辦法。假如拜托應用援用參數,援用將按相反的次序傳遞到一切這三個辦法,而且一種辦法停止的任何更改都將在另外一種辦法上見到。當辦法激發未在辦法內捕捉到的異常時,該異常將傳遞到拜托的挪用方,而且不會挪用挪用列表中的後續辦法。假如拜托具有前往值和/或輸入參數,它將前往前次挪用辦法的前往值和參數。若要刪除挪用列表中的辦法,請應用減法運算符或減法賦值運算符(“+”或“+=”)。例如:
//remove Method1 allMethodsDelegate -= d1; // copy AllMethodsDelegate while removing d2 Del oneMethodDelegate = allMethodsDelegate - d2;
因為拜托類型派生自 System.Delegate,是以可以在拜托上挪用該類界說的辦法和屬性。例如,若要查詢拜托挪用列表中辦法的數目,你可以編寫:
int invocationCount = d1.GetInvocationList().GetLength(0);
挪用列表中具有多個辦法的拜托派生自 MulticastDelegate,該類屬於 System.Delegate 的子類。因為這兩個類都支撐 GetInvocationList,是以在其他情形下,上述代碼也將發生感化。
多播拜托普遍用於事宜處置中。事宜源對象將事宜告訴發送到已注冊吸收該事宜的吸收方對象。若要注冊一個事宜,吸收方須要創立用於處置該事宜的辦法,然後為該辦法創立拜托並將拜托傳遞到事宜源。事宜產生時,源挪用拜托。然後,拜托將對吸收方挪用事宜處置辦法,從而供給事宜數據。給定事宜的拜托類型由事宜源肯定。有關具體信息,請參閱事宜(C# 編程指南)。
在編譯時比擬分派的兩個分歧類型的拜托將招致編譯毛病。假如拜托實例是靜態的 System.Delegate 類型,則許可比擬,但在運轉時將前往 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); }
帶有定名辦法的拜托與帶有匿名辦法的拜托
拜托可以與定名辦法聯系關系。應用定名辦法對拜托停止實例化時,該辦法將作為參數傳遞,例如:
// 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;
這被稱為應用定名的辦法。應用定名辦法結構的拜托可以封裝靜態辦法或實例辦法。在晚期版本的 C# 中,定名辦法是對拜托停止實例化的獨一方法。然則,在不願望支付創立新辦法的體系開支時,C# 使您可以對拜托停止實例化,並立刻指定拜托在被挪用時將處置的代碼塊。代碼塊可以包括 lambda 表達式或匿名辦法。
備注:作為拜托參數傳遞的辦法必需與拜托聲明具有雷同的簽名。
拜托實例可以封裝靜態或實例辦法。
雖然拜托可使用 out 參數,但建議您不要將其用於多路播送事宜拜托,由於您沒法曉得哪一個拜托將被挪用。
示例 1
以下是聲明及應用拜托的一個簡略示例。留意,拜托 Del 和聯系關系的辦法 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
鄙人面的示例中,一個拜托被同時映照到靜態辦法和實例辦法,並分離前往特定的信息。
// 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.