<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # C# 委托 > 原文: [https://zetcode.com/lang/csharp/delegates/](https://zetcode.com/lang/csharp/delegates/) C# 教程的這一部分專門針對委托。 委托是.NET Framework 使用的一種類型安全的函數指針。 委托通常用于實現回調和事件監聽器。 委托無需了解其使用的方法類的任何知識。 委托是引用類型。 但是委托不是引用對象,而是引用方法。 在以下情況下使用委托: * 事件處理器 * 回調 * LINQ * 設計模式的實現 委托沒有什么可以用常規方法完成的。 之所以使用委托,是因為它們帶來了許多優點。 它們提高了應用和代碼重用的靈活性。 像接口一樣,委托使我們能夠解耦和泛化我們的代碼。 委托還允許將方法作為參數傳遞。 當我們需要確定在運行時調用哪種方法時,可以使用委托。 最后,委托提供了一種無需對子類進行子類化就可以對它的行為進行專門化的方法。 類可能具有復雜的泛型行為,但仍應專門化。 類是通過繼承或通過委托來專用的。 ## C# 使用委托 我們將有一些簡單的示例顯示如何使用委托。 `Program.cs` ```cs using System; namespace SimpleDelegate { delegate void MyDelegate(); class Program { static void Main(string[] args) { var md = new MyDelegate(MyCallback); md(); } static void MyCallback() { Console.WriteLine("Calling callback"); } } } ``` 我們聲明一個委托,創建該委托的實例并調用它。 ```cs delegate void MyDelegate(); ``` 這是我們的委托聲明。 它不返回任何值,不接受任何參數。 ```cs var md = new MyDelegate(MyCallback); ``` 我們創建委托的實例。 調用時,委托將調用靜態`Callback()`方法。 ```cs md(); ``` 我們打電話給委托。 ```cs $ dotnet run Calling callback ``` 這是輸出。 我們可以使用不同的語法來創建和使用委托。 `Program.cs` ```cs using System; namespace SimpleDelegate2 { delegate void MyDelegate(); class Program { static void Main(string[] args) { MyDelegate del = MyCallback; del(); } static void MyCallback() { Console.WriteLine("Calling callback"); } } } ``` 創建委托的實例時,我們可以保存一些類型。 ```cs MyDelegate del = MyCallback; ``` 這是創建委托的另一種方法。 我們直接指向方法名稱。 ## C# 委托指向不同的方法 委托可以隨著時間指向不同的方法。 `Program.cs` ```cs using System; namespace DifferentMethods { public delegate void NameDelegate(string msg); public class Person { public string firstName; public string secondName; public Person(string firstName, string secondName) { this.firstName = firstName; this.secondName = secondName; } public void ShowFirstName(string msg) { Console.WriteLine(msg + this.firstName); } public void ShowSecondName(string msg) { Console.WriteLine(msg + this.secondName); } } class Program { public static void Main() { var per = new Person("Fabius", "Maximus"); var nDelegate = new NameDelegate(per.ShowFirstName); nDelegate("Call 1: "); nDelegate = new NameDelegate(per.ShowSecondName); nDelegate("Call 2: "); } } } ``` 在此示例中,我們只有一名委托。 該委托用于指向`Person`類的兩個方法。 方法與委托一起調用。 ```cs public delegate void NameDelegate(string msg); ``` 使用`delegate`關鍵字創建委托。 委托簽名必須與委托調用的方法的簽名匹配。 ```cs var nDelegate = new NameDelegate(per.ShowFirstName); nDelegate("Call 1: "); ``` 我們創建一個新委托的實例,該實例指向`ShowFirstName()`方法。 稍后我們通過委托調用該方法。 ```cs $ dotnet run Call 1: Fabius Call 2: Maximus ``` 這兩個名稱都是通過委托打印的。 ## C# 多播委托 多播委托是一個擁有對多個方法的引用的委托。 多播委托必須僅包含返回`void`的方法,否則將存在運行時異常。 `Program.cs` ```cs using System; namespace MulticastDelegate { delegate void MyDelegate(int x, int y); public class Oper { public static void Add(int x, int y) { Console.WriteLine("{0} + {1} = {2}", x, y, x + y); } public static void Sub(int x, int y) { Console.WriteLine("{0} - {1} = {2}", x, y, x - y); } } class Program { static void Main() { var del = new MyDelegate(Oper.Add); del += new MyDelegate(Oper.Sub); del(6, 4); del -= new MyDelegate(Oper.Sub); del(2, 8); } } } ``` 這是一個多播委托的示例。 ```cs delegate void MyDelegate(int x, int y); ``` 我們的委托接受兩個參數。 我們有一個`Oper`類,它具有兩個靜態方法。 一個將兩個值相加,另一個將兩個值相減。 ```cs var del = new MyDelegate(Oper.Add); ``` 我們創建委托的實例。 委托指向`Oper`類的靜態`Add()`方法。 ```cs del += new MyDelegate(Oper.Sub); del(6, 4); ``` 我們將另一個方法插入到現有的委托實例中。 委托的第一次調用將調用兩個方法。 ```cs del -= new MyDelegate(Oper.Sub); del(2, 8); ``` 我們從委托中刪除一種方法。 委托的第二次調用僅調用一種方法。 ```cs $ dotnet run 6 + 4 = 10 6 - 4 = 2 2 + 8 = 10 ``` 這是程序的輸出。 ## C# 匿名方法 可以對委托使用匿名方法。 `Program.cs` ```cs using System; namespace Anonymous { delegate void MyDelegate(); class Program { static void Main(string[] args) { MyDelegate del = delegate { Console.WriteLine("Anonymous method"); }; del(); } } } ``` 當將匿名方法與委托一起使用時,我們可以省略方法聲明。 該方法沒有名稱,只能通過委托來調用。 ```cs MyDelegate del = delegate { Console.WriteLine("Anonymous method"); }; ``` 在這里,我們創建一個指向匿名方法的委托。 匿名方法的主體用`{}`字符括起來,但是沒有名稱。 ## C# 委托作為方法參數 委托可以用作方法參數。 `Program.cs` ```cs using System; namespace MethodParameters { delegate int Arithm(int x, int y); class Program { static void Main() { DoOperation(10, 2, Multiply); DoOperation(10, 2, Divide); } static void DoOperation(int x, int y, Arithm del) { int z = del(x, y); Console.WriteLine(z); } static int Multiply(int x, int y) { return x * y; } static int Divide(int x, int y) { return x / y; } } } ``` 我們有一個`DoOperation()`方法,該方法將一個委托作為參數。 ```cs delegate int Arithm(int x, int y); ``` 這是一個委托聲明。 ```cs static void DoOperation(int x, int y, Arithm del) { int z = del(x, y); Console.WriteLine(z); } ``` 這是`DoOperation()`方法的實現。 第三個參數是委托。 `DoOperation()`方法調用一個方法,該方法作為第三個參數傳遞給它。 ```cs DoOperation(10, 2, Multiply); DoOperation(10, 2, Divide); ``` 我們稱為`DoOperation()`方法。 我們傳遞兩個值和一個方法給它。 我們對這兩個值的處理方式取決于我們通過的方法。 這就是使用委托所帶來的靈活性。 ```cs $ dotnet run 20 5 ``` This is the output. ## C# 事件 事件是由某些操作觸發的消息。 單擊按鈕或滴答滴答即是這種動作。 觸發事件的對象稱為發送者,而接收事件的對象稱為接收者。 按照約定,.NET Framework 中的事件委托具有兩個參數:引發事件的源和事件的數據。 `Program.cs` ```cs using System; namespace SimpleEvent { public delegate void OnFiveHandler(object sender, EventArgs e); class FEvent { public event OnFiveHandler FiveEvent; public void OnFiveEvent() { if (FiveEvent != null) { FiveEvent(this, EventArgs.Empty); } } } class Program { static void Main() { var fe = new FEvent(); fe.FiveEvent += new OnFiveHandler(Callback); var random = new Random(); for (int i = 0; i < 10; i++) { int rn = random.Next(6); Console.WriteLine(rn); if (rn == 5) { fe.OnFiveEvent(); } } } public static void Callback(object sender, EventArgs e) { Console.WriteLine("Five Event occurred"); } } } ``` 我們有一個簡單的示例,可以在其中創建和啟動事件。 生成一個隨機數。 如果數字等于 5,則會生成`FiveEvent`事件。 ```cs public event OnFiveHandler FiveEvent; ``` 使用`event`關鍵字聲明事件。 ```cs fe.FiveEvent += new OnFiveHandler(Callback); ``` 在這里,我們將名為`FiveEvent`的事件插入到`Callback()`方法中。 換句話說,如果觸發了`ValueFive`事件,則將執行`Callback()`方法。 ```cs public void OnFiveEvent() { if(FiveEvent != null) { FiveEvent(this, EventArgs.Empty); } } ``` 當隨機數等于 5 時,我們調用`OnFiveEvent()`方法。 在這種方法中,我們引發了`FiveEvent`事件。 此事件不包含任何參數。 ```cs $ dotnet run 1 1 5 Five Event occurred 1 1 4 1 2 4 5 Five Event occurred ``` 這是一個示例輸出。 ## C# 復雜事件示例 接下來,我們有一個更復雜的示例。 這次,我們將通過生成的事件發送一些數據。 `Program.cs` ```cs using System; namespace ComplexEvent { public delegate void OnFiveHandler(object sender, FiveEventArgs e); public class FiveEventArgs : EventArgs { public int count; public DateTime time; public FiveEventArgs(int count, DateTime time) { this.count = count; this.time = time; } } public class FEvent { public event OnFiveHandler FiveEvent; public void OnFiveEvent(FiveEventArgs e) { FiveEvent(this, e); } } public class RandomEventGenerator { public void Generate() { int count = 0; FiveEventArgs args; var fe = new FEvent(); fe.FiveEvent += new OnFiveHandler(Callback); var random = new Random(); for (int i = 0; i < 10; i++) { int rn = random.Next(6); Console.WriteLine(rn); if (rn == 5) { count++; args = new FiveEventArgs(count, DateTime.Now); fe.OnFiveEvent(args); } } } public void Callback(object sender, FiveEventArgs e) { Console.WriteLine("Five event {0} occurred at {1}", e.count, e.time); } } class Program { static void Main() { var reg = new RandomEventGenerator(); reg.Generate(); } } } ``` 我們有四個類。 `FiveEventArgs`帶有事件對象的一些數據。 `FEvent`類封裝了事件對象。 `RandomEventGenerator`類負責生成隨機數。 它是事件發送者。 最后,`ComplexEvent`是主要的應用類。 ```cs public class FiveEventArgs : EventArgs { public int count; public DateTime time; ... ``` `FiveEventArgs`在事件對象內部傳送數據。 它繼承自`EventArgs`基類。 計數和時間成員是將被初始化并隨事件一起攜帶的數據。 ```cs if (rn == 5) { count++; args = new FiveEventArgs(count, DateTime.Now); fe.OnFiveEvent(args); } ``` 如果生成的隨機數等于 5,我們用當前計數和`DateTime`值實例化`FiveEventArgs`類。 `count`變量對生成此事件的次數進行計數。 `DateTime`值保存事件生成的時間。 ```cs $ dotnet run 4 4 1 3 3 3 2 5 Five event 1 occurred at 10/22/2019 2:13:10 PM 3 0 ``` 這是程序的示例輸出。 ## C# 預定義的委托 .NET 框架具有多個內置的委托,這些委托減少了所需的輸入并簡化了開發者的編程工作。 ### C# 動作委托 操作委托封裝了沒有參數且不返回值的方法。 `Program.cs` ```cs using System; namespace ActionDelegate { class Program { static void Main() { Action act = ShowMessage; act(); } static void ShowMessage() { Console.WriteLine("C# language"); } } } ``` 使用預定義的委托可以進一步簡化編程。 我們不需要聲明委托類型。 ```cs Action act = ShowMessage; act(); ``` 我們實例化一個動作委托。 委托指向`ShowMessage()`方法。 調用委托時,將執行`ShowMessage()`方法。 有多種類型的動作委托。 例如,`Action<T>`委托封裝了一個采用單個參數且不返回值的方法。 `Program.cs` ```cs using System; namespace ActionDelegate2 { class Program { static void Main() { Action<string> act = ShowMessage; act("C# language"); } static void ShowMessage(string message) { Console.WriteLine(message); } } } ``` 我們修改前面的示例,以使用帶有一個參數的動作委托。 ```cs Action<string> act = ShowMessage; act("C# language"); ``` 我們創建`Action<T>`委托的實例,并使用一個參數對其進行調用。 ### C# 謂詞委托 謂詞是一種返回`true`或`false`的方法。 謂詞委托是對謂詞的引用。 謂詞對于過濾值列表非常有用。 `Program.cs` ```cs using System; using System.Collections.Generic; namespace PredicateDelegate { class Program { static void Main() { List<int> vals = new List<int> { 4, 2, 3, 0, 6, 7, 1, 9 }; Predicate<int> myPred = greaterThanThree; List<int> vals2 = vals.FindAll(myPred); foreach (int i in vals2) { Console.WriteLine(i); } } static bool greaterThanThree(int x) { return x > 3; } } } ``` 我們有一個整數值列表。 我們要過濾所有大于三的數字。 為此,我們使用謂詞委托。 ```cs List<int> vals = new List<int> { 4, 2, 3, 0, 6, 7, 1, 9 }; ``` 這是整數值的一般列表。 ```cs Predicate<int> myPred = greaterThanThree; ``` 我們創建一個謂詞委托的實例。 委托指向謂詞,這是一種返回`true`或`false`的特殊方法。 ```cs List<int> vals2 = vals.FindAll(myPred); ``` `FindAll()`方法檢索與指定謂詞定義的條件匹配的所有元素。 ```cs static bool greaterThanThree(int x) { return x > 3; } ``` 對于大于三個的所有值,謂詞返回`true`。 C# 教程的這一部分專用于委托。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看