首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 委派深度解析:從基礎語法到多播、匿名方法、參數傳遞與返回值實戰

     編輯:關於C語言

委派 是 C# 中極重要的概念,廣泛應用於事件、執行緒、回呼等場景。本質上,委派是參考方法的型別。一旦指派方法,委派即擁有該方法完全相同的行為,可像一般方法一樣擁有參數與回傳值。

委派核心特性

  • 類似 C++ 函式指標,但型別安全
  • 允許將方法作為參數傳遞
  • 可定義回呼方法
  • 支援多播:串聯多個方法
  • 方法簽名支援協變與逆變,不需完全匹配
  • C# 2.0 引入匿名方法,允許程式碼區塊直接當參數

使用委派三步驟

  1. 定義委派:public delegate void MyDel();
  2. 實例化委派:MyDel del = new MyDel(obj.Method); 或 C# 2.0 簡寫 MyDel del = obj.Method;
  3. 呼叫委派:del();

完整程式碼示範

namespace DelegateDemo
{
    // 各類委派宣告
    public delegate void MyDel();
    public delegate void MyDel2(int num1, int num2);
    public delegate string MyDel3(string s);
    public delegate string ProcessString(string s);

    class Program
    {
        static void Main(string[] args)
        {
            TestDel t = new TestDel();
            
            #region 基礎委派實例化與呼叫
            MyDel del = new MyDel(t.MyMethod);
            del();
            
            // C# 2.0 簡寫
            MyDel del4 = t.MyMethod;
            del4();
            
            // 靜態方法
            del4 = TestDel.MyStaticMethod;
            del4();
            
            // 帶參數委派
            MyDel2 del2 = t.MyMethod;
            del2(10, 20);
            
            // 帶回傳值委派
            MyDel3 del3 = t.MyMethod;
            Console.WriteLine(del3("abc"));
            #endregion
            
            #region 匿名方法
            Console.WriteLine("-----匿名方法演示-----");
            ProcessString p = delegate(string inputString)
            {
                return inputString.ToUpper();
            };
            Console.WriteLine(p("aaaa"));
            #endregion
            
            #region 多播委派
            Console.WriteLine("-----多播委派演示-----");
            MyDel mydel1 = t.MyMethod;
            MyDel mydel2 = t.MyMethod2;
            MyDel mydel3 = TestDel.MyMethod3;
            MyDel allMyDel = mydel1 + mydel2 + mydel3;
            allMyDel();  // 依序執行三個方法
            allMyDel -= mydel3;
            allMyDel();  // 僅執行前兩個
            #endregion
            
            #region 委派作為參數
            Console.WriteLine("-----委派作為參數-----");
            MyDel3 paramMyDel3 = t.MyMethod;
            TestDel.MyParamMethod("aaa", paramMyDel3);
            #endregion
            
            #region 委派作為回傳值
            Console.WriteLine("-----委派作為回傳值-----");
            MyDel3 returnMyDel = t.MyReturnMethod();
            Console.WriteLine(returnMyDel("sssssssssssss"));
            #endregion
        }
    }

    public class TestDel
    {
        public static void MyStaticMethod() => Console.WriteLine("My Static Method");
        public void MyMethod() => Console.WriteLine("MyMethod");
        public void MyMethod2() => Console.WriteLine("My Method 22222222222");
        public static void MyMethod3() => Console.WriteLine("My Method 3333333333333");
        public void MyMethod(int num1, int num2) => Console.WriteLine(num1 + num2);
        public string MyMethod(string s) => s.ToUpper();
        
        // 委派作為參數
        public static void MyParamMethod(string s, MyDel3 del3) => Console.WriteLine(del3(s));
        
        // 委派作為回傳值
        public MyDel3 MyReturnMethod() => MyMethod;
    }
}

實戰應用範例

委派作為參數:書籍處理系統

public delegate void ProcessBook(Book b);

public class BookDB
{
    public List books = new List();
    public void AddBook(Book b) => books.Add(b);
    
    public void PrintBook(ProcessBook process)
    {
        foreach (var book in books)
            process(book);
    }
}

public class MyParamDelegateTest
{
    BookDB bookDB = new BookDB();
    double total = 0;
    
    public void AddBooks()
    {
        bookDB.AddBook(new Book { BookID = 1, BookName = "C#", Price = 123, IsPaperbook = true });
        bookDB.AddBook(new Book { BookID = 1, BookName = "C#", Price = 123, IsPaperbook = false });
        bookDB.AddBook(new Book { BookID = 2, BookName = "ASP.Net", Price = 12, IsPaperbook = true });
        bookDB.AddBook(new Book { BookID = 1, BookName = "ADO", Price = 23, IsPaperbook = false });
    }
    
    public void TestProcessBook(Book b)
    {
        if (b.IsPaperbook) Console.WriteLine(b.BookName);
    }
    
    public void TotalPrice(Book b) => total += b.Price;
    
    public void MyTest()
    {
        bookDB.PrintBook(TestProcessBook);  // 列印實體書名稱
        bookDB.PrintBook(TotalPrice);       // 計算總價
        Console.WriteLine(total);
    }
}

public class Book
{
    public int BookID { get; set; }
    public string BookName { get; set; }
    public double Price { get; set; }
    public bool IsPaperbook { get; set; }
}

委派作為回傳值:簡易計算機

public delegate int MyReturnDelegate(int num1, int num2);

public class MyCalcuate
{
    public MyReturnDelegate Calcuate(string oper)
    {
        MyReturnDelegate myReturn = null;
        switch (oper)
        {
            case "+": myReturn = delegate(int n1, int n2) { return n1 + n2; }; break;
            case "-": myReturn = delegate(int n1, int n2) { return n1 - n2; }; break;
            case "*": myReturn = delegate(int n1, int n2) { return n1 * n2; }; break;
            case "/": myReturn = delegate(int n1, int n2) { return n1 / n2; }; break;
        }
        return myReturn;
    }
}

public class MyReturnDelegateTest
{
    public void MyTest()
    {
        MyCalcuate myCalcuate = new MyCalcuate();
        do
        {
            Console.WriteLine("請輸入運算符號 (+ - * /)");
            string oper = Console.ReadLine();
            Console.WriteLine("請輸入運算元 1"); string num1 = Console.ReadLine();
            Console.WriteLine("請輸入運算元 2"); string num2 = Console.ReadLine();
            
            MyReturnDelegate myReturn = myCalcuate.Calcuate(oper);
            int result = myReturn(int.Parse(num1), int.Parse(num2));
            Console.WriteLine($"{num1}{oper}{num2}={result}");
            
            Console.WriteLine("繼續嗎? Y/N");
        } while (Console.ReadLine().ToUpper() != "N");
    }
}

現代 C# 演進

C# 3.0 引入 Lambda 運算式 (=>) 取代匿名方法,語法更簡潔;C# 內建 Func<T, TResult>、Action<T> 等泛型委派,減少自訂委派宣告。但理解傳統委派機制,仍是掌握事件、LINQ、非同步程式設計的基石。

原文連結:https://www.cnblogs.com/yangyancheng/archive/2011/04/21/2024145.html
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved