C# 委托(Delegate)

如果我們想將函數(shù)作為參數(shù)傳遞怎么辦?C#如何處理回調(diào)函數(shù)或事件處理程序?答案是-委托(delegate)。委托(Delegate) 是存有對某個(gè)方法的引用的一種引用類型變量。引用可在運(yùn)行時(shí)被改變。

委托是定義方法簽名的引用類型數(shù)據(jù)類型。您可以定義委托的變量,就像其他數(shù)據(jù)類型一樣,這些變量可以引用與委托具有相同簽名的任何方法。

與委托一起工作涉及三個(gè)步驟:

  1. 聲明委托

  2. 設(shè)置目標(biāo)方法

  3. 調(diào)用委托

可以使用delegate關(guān)鍵字和函數(shù)簽名來聲明委托,如下所示。

  委托語法

[access modifier] delegate [return type] [delegate name]([parameters])

以下聲明了一個(gè)名為 MyDelegate 的委托。

public delegate void MyDelegate(string msg);

上面,我們聲明了一個(gè) MyDelegate 帶有void返回類型和字符串參數(shù)??梢栽陬愅獠炕蝾悆?nèi)部聲明委托。實(shí)際上,應(yīng)該在類之外聲明它。

聲明委托后,我們需要設(shè)置目標(biāo)方法 或 lambda表達(dá)式。我們可以通過使用 new 關(guān)鍵字創(chuàng)建委托的對象并傳遞其簽名與委托簽名匹配的方法來實(shí)現(xiàn)。

public delegate void MyDelegate(string msg); // 聲明委托

//設(shè)定目標(biāo)方法
MyDelegate del = new MyDelegate(MethodA);
// 或者
MyDelegate del = MethodA; 
// 或者 lambda 表達(dá)式 
MyDelegate del = (string msg) =>  Console.WriteLine(msg);

// 目標(biāo)方法
static void MethodA(string message)
{
    Console.WriteLine(message);
}

您可以通過直接分配方法來設(shè)置目標(biāo)方法,而無需創(chuàng)建委托的對象,例如MyDelegate del = MethodA。

設(shè)置目標(biāo)方法后,可以使用 Invoke()方法或使用()運(yùn)算符來調(diào)用委托。

del.Invoke("Hello World!");
//或者 
del("Hello World!");

以下是委托的完整示例。

public delegate void MyDelegate(string msg); //聲明委托

class Program
{
    static void Main(string[] args)
    {
        MyDelegate del = ClassA.MethodA;
        del("Hello World");

        del = ClassB.MethodB;
        del("Hello World");

        del = (string msg) => Console.WriteLine("Called lambda expression: " + msg);
        del("Hello World");
    }
}

class ClassA
{
    static void MethodA(string message)
    {
        Console.WriteLine("Called ClassA.MethodA() with parameter: " + message);
    }
}

class ClassB
{
    static void MethodB(string message)
    {
        Console.WriteLine("Called ClassB.MethodB() with parameter: " + message);
    }
}

下圖說明了委托。

C#中的委托
C#委托

將委托作為參數(shù)傳遞

方法可以具有委托類型的參數(shù),如下所示。

public delegate void MyDelegate(string msg); //聲明委托

class Program
{
    static void Main(string[] args)
    {
        MyDelegate del = ClassA.MethodA;
        InvokeDelegate(del);

        del = ClassB.MethodB;
        InvokeDelegate(del);

        del = (string msg) => Console.WriteLine("Called lambda expression: " + msg);
        InvokeDelegate(del);
    }

    static void InvokeDelegate(MyDelegate del) // MyDelegate類型參數(shù)
    {
        del("Hello World");
    }
}

class ClassA
{
    static void MethodA(string message)
    {
        Console.WriteLine("Called ClassA.MethodA() with parameter: " + message);
    }
}

class ClassB
{
    static void MethodB(string message)
    {
        Console.WriteLine("Called ClassB.MethodB() with parameter: " + message);
    }
}

在.NET中,F(xiàn)unc和Action類型是內(nèi)置的泛型委托,應(yīng)該用于最常見的委托,而不是創(chuàng)建新的自定義委托。

組播委托

委托可以指向多個(gè)方法。指向多個(gè)方法的委托稱為多播委托?!?”或“+=”運(yùn)算符將函數(shù)添加到調(diào)用列表中,而“-”和“-=”運(yùn)算符將其刪除。

public delegate void MyDelegate(string msg); //宣聲明委托

class Program
{
    static void Main(string[] args)
    {
        MyDelegate del1 = ClassA.MethodA;
        MyDelegate del2 = ClassB.MethodB;

        MyDelegate del = del1 + del2; // del1 + del2
        del("Hello World");

        MyDelegate del3 = (string msg) => Console.WriteLine("Called lambda expression: " + msg);
        del += del3; // del1 + del2 + del3
        del("Hello World");

        del = del - del2; // 移除 del2
        del("Hello World");

        del -= del1 // 移除 del1
        del("Hello World");
    }
}

class ClassA
{
    static void MethodA(string message)
    {
        Console.WriteLine("Called ClassA.MethodA() with parameter: " + message);
    }
}

class ClassB
{
    static void MethodB(string message)
    {
        Console.WriteLine("Called ClassB.MethodB() with parameter: " + message);
    }
}

加法和減法運(yùn)算符始終作為賦值的一部分工作:del1+=del2;與del1=del1+del2完全等價(jià);減法也是如此。

如果委托返回一個(gè)值,那么當(dāng)多播委托調(diào)用時(shí),最后分配的目標(biāo)方法的值將被返回。

public delegate int MyDelegate(); //聲明委托

class Program
{
    static void Main(string[] args)
    {
        MyDelegate del1 = ClassA.MethodA;
        MyDelegate del2 = ClassB.MethodB;

        MyDelegate del = del1 + del2; 
        Console.WriteLine(del());// 返回200
    }
}

class ClassA
{
    static int MethodA()
    {
        return 100;
    }
}

class ClassB
{
    static int MethodB()
    {
        return 200;
    }
}

泛型委托

可以使用與委托相同的方式定義泛型委托,但可以使用泛型type參數(shù)或返回類型。 設(shè)置目標(biāo)方法時(shí),必須指定泛型類型。

例如,看以下用于int和string參數(shù)的通用委托。

public delegate T add<T>(T param1, T param2); // 泛型委托

class Program
{
    static void Main(string[] args)
    {
        add<int> sum = Sum;
        Console.WriteLine(sum(10, 20));

        add<string> con = Concat;
        Console.WriteLine(conct("Hello ","World!!"));
    }

    public static int Sum(int val1, int val2)
    {
        return val1 + val2;
    }

    public static string Concat(string str1, string str2)
    {
        return str1 + str2;
    }
}

委托還用于聲明事件和匿名方法。

 要記住的要點(diǎn)

  1. 委托是定義簽名的引用類型數(shù)據(jù)類型。

  2. 委托類型變量可以引用具有與委托相同簽名的任何方法。

  3. 語法:[訪問修飾符]委托[返回類型] [委托名稱]([參數(shù)])([access modifier] delegate [return type] [delegate name]([parameters]))

  4. 目標(biāo)方法的簽名必須與委托簽名匹配。

  5. 委托可以像普通函數(shù)或invoke()方法一樣被調(diào)用。

  6. 可以使用“ +”或“ + =”運(yùn)算符將多個(gè)方法分配給委托,并使用“-”或“-=”運(yùn)算符將其刪除。它稱為多播委托。

  7. 如果多播委托返回一個(gè)值,則它從最后分配的目標(biāo)方法中返回該值。

  8. 委托用于在C#中聲明事件和匿名方法。

丰满人妻一级特黄a大片,午夜无码免费福利一级,欧美亚洲精品在线,国产婷婷成人久久Av免费高清