C# 委托 01

2019-08-21  本文已影响0人  JeetChan

声明

本文内容来自微软 MVP solenovex 的视频教程——真会C#? - 第4章 委托、事件、Lambda表达式(完结),大致和第 1 课—— 4.1 委托(上) 对应。可在 GitHub 中查看 C# 视频教程的配套PPT

本文主要包括以下内容:

  1. 委托类型和委托实例
  2. 编写插件式的方法
  3. 多播委托

Delegates 委托

委托是一个对象,它知道如何调用一个方法。

委托类型和委托实例

委托类型定义了委托实例可以调用的那类方法,具体来说,委托类型定义了方法的返回类型和参数。

delegate int Transformer (int x);

static int Square (int x) { return x * x; }

// static int Square (int x) => x * x;

委托实例

把方法赋值给委托变量的时候就创建了委托实例。Transformer t = Square;调用:int answer = t(3); // answer is 9

委托的实例其实就是调用者的委托:调用者调用委托,然后委托调用目标方法。间接的把调用者和目标方法解耦合了。

编写插件式的方法

方法是在运行时才赋值给委托变量的。

public delegate int Transformer (int x);

class Util
{
    public static void Transform (int[] values, Transformer t)
    {
        for (int i = 0; i < values.Length; i++)
            values[i] = t (values[i]);
    }
}

class Test
{
    static void Main()
    {
        int[] values = { 1, 2, 3 };
        Util.Transform (values, Square); // Hook in the Square method
        foreach (int i in values)
            Console.Write (i + " "); // 1 4 9
    }
    
    static int Square (int x) => x * x;
}

多播委托

所有的委托实例都具有多播的能力。一个委托实例可以引用一组目标方法。

+ 和 += 操作符可以合并委托实例。

SomeDelegate d = SomeMethod1;
d += SomeMethod2;

d = d + SomeMethod2;

调用 d 就会调用 SomeMethod1 和 SomeMethod2,委托的调用顺序与它们的定义顺序一致。

- 和 -= 会把右边的委托从左边的委托里移除。d -= SomeMethod1;

委托变量使用 ++= 操作符时,其操作数可以是 null。就相当于把一个新的值赋给了委托变量。

SomeDelegate d = null;
d += SomeMethod1; // Equivalent (when d is null) to d = SomeMethod1;

对单个目标方法的委托变量使用-=操作符时,就相当于把null值赋给了委托变量。

委托是不可变的,使用+=-=操作符时,实际上是创建了新的委托实例,并把它赋给当前的委托变量。

如果多播委托的返回类型不是void,那么调用者从最后一个被调用的方法来接收返回值。前面的方法仍然会被调用,但是其返回值就被弃用了。

所有的委托类型都派生于 System.MulticastDelegate,而它又派生于System.Delegate。C# 会把作用于委托的+-+=-=操作编译成使用System.DelegateCombineRemove两个静态方法。

多播委托例子

public delegate void ProgressReporter (int percentComplete);

public class Util
{
    public static void HardWork (ProgressReporter p)
    {
        for (int i = 0; i < 10; i++)
        {
            p (i * 10); // Invoke delegate
            System.Threading.Thread.Sleep (100); // Simulate hard work
        }
    }
}

class Test
{
    static void Main()
    {
        ProgressReporter p = WriteProgressToConsole;
        p += WriteProgressToFile;
        Util.HardWork (p);
    }
    
    static void WriteProgressToConsole(intpercentComplete)=>Console.WriteLine (percentComplete);

    static void WriteProgressToFile (int percentComplete)=>System.IO.File.WriteAllText ("progress.txt",
percentComplete.ToString());

}
c# 委托

参考

Delegates (C# Programming Guide)
Delegate Class
MulticastDelegate Class

上一篇 下一篇

猜你喜欢

热点阅读