C# 中的委托:Delegate

  引用官方的话:委托 是一种引用类型,表示对具有特定参数列表和返回类型的方法的引用。
  简而言之,委托就是方法参数化。类似于 Javascript 中的回调函数,也是将函数参数化的用例。至于 委托 有何妙用呢?且看下方道来!

项目准备

  创建如下所示控制台应用程序:

在这里插入图片描述
  在文件 Program.cs 中写一个求和的方法 sumFunc() ,代码如下所示:

using System;

namespace DelegateDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
		// 委托所调用的函数
        private static int sumFunc(int a, int b)
        {
            return a + b;
        }
    }
}

委托的声明、初始化以及使用

委托的声明和初始化

  在使用委托之前,需要使用关键字 delegate 来对委托进行申明,委托的申明可以通过以下几种方式进行:
  1. 最早的申明方式,在 C# 1.0 及更高版本可以使用以下示例进行申明:

class Program
{
    // 申明委托 GetSum,委托修饰符:delegate
    private delegate int GetSum(int a, int b);
    static void Main(string[] args)
    {
        // 实例化委托 sum
        GetSum sum = new GetSum(sumFunc);
        Console.ReadLine();
    }
	// 委托所调用的函数
    private static int sumFunc(int a,int b)
    {
        return a+b;
    }
}

  2. 自 C# 2.0 以后 C# 提供了一种简单的申明实例化方式:

class Program
{
    // 申明委托 GetSum,委托修饰符:delegate
    private delegate int GetSum(int a, int b);
    static void Main(string[] args)
    {
        // 实例化委托 sum。差别在这里 ↓
        GetSum sum = sumFunc;
        Console.ReadLine();
    }
	// 委托所调用的函数
    private static int sumFunc(int a, int b)
    {
        return a + b;
    }
}

  3. 还可以通过 匿名函数 的形式来声明和初始化委托,如下所示:

class Program
{
    // 申明委托 GetSum,委托修饰符:delegate
    private delegate int GetSum(int a, int b);
    static void Main(string[] args)
    {
        // 实例化委托 sum。差别在这里 ↓
        GetSum sum = delegate (int a, int b) { return a + b; };
        Console.ReadLine();
    }
}

  4. 还可以通过 lambda 表达式的方式申明和实例化委托,如下所示:

class Program
{
    // 申明委托 GetSum,委托修饰符:delegate
    private delegate int GetSum(int a, int b);
    static void Main(string[] args)
    {
        // 实例化委托 sum。差别在这里 ↓
        GetSum sum = (a, b) => { return a + b; };
        Console.ReadLine();
    }
}

委托的使用示例

  示例一:

class Program
{
    // 申明委托 GetSum,委托修饰符:delegate
    private delegate int GetSum(int a, int b);
    static void Main(string[] args)
    {
        // 实例化委托 sum。
        GetSum sum = sumFunc;
        // 使用委托
        int _sum = sum(3, 4);
        Console.WriteLine($"计算结果:{_sum}");
        Console.ReadLine();
    }

    private static int sumFunc(int a, int b)
    {
        return a + b;
    }
}

  方式二: 创建一个计算乘法的函数法,计算出 (a+b)*a 的值。

class Program
{
    // 申明委托 GetSum,委托修饰符:delegate
    private delegate int GetSum(int a, int b);
    static void Main(string[] args)
    {
        // 实例化委托 sum。
        GetSum sum = sumFunc;
        // 使用委托
        int _multiply = multiplyFunc(sum, 3, 4);
        Console.WriteLine($"计算结果:{_multiply}");
        Console.ReadLine();
    }

    private static int sumFunc(int a, int b)
    {
        return a + b;
    }
    private static int multiplyFunc(GetSum sum, int a, int b)
    {
        return sum(a, b) * a;
    }
}

委托的合并

  委托可以合并多个方法,也可以移除合并方法中的其中之一。可通过 +- 进行委托的绑定和移除。建立如下示例代码:

class Program
{
    // 申明委托 GetSum,委托修饰符:delegate
    private delegate void Execution();
    static void Main(string[] args)
    {
        // 实例化委托 sum。
        Execution fun = Func1;
        fun += Func2;
        fun += Func3;
        Console.WriteLine("委托执行结果:");
        fun();
        fun -= Func2;
        Console.WriteLine("移除的执行结果:");
        fun();
        Console.ReadLine();
    }

    private static void Func1()
    {
        Console.WriteLine("函数 Func1() 执行。");
    }
    private static void Func2()
    {
        Console.WriteLine("函数 Func2() 执行。");
    }
    private static void Func3()
    {
        Console.WriteLine("函数 Func3() 执行。");
    }
}

  这里合并到一起的那几个方法会根据顺序依次执行,执行结果如下:

委托执行结果:
函数 Func1() 执行。
函数 Func2() 执行。
函数 Func3() 执行。
移除的执行结果:
函数 Func1() 执行。
函数 Func3() 执行。

类库中的委托

  MSCorLib.dll中,有将近50个委托类型:

public delegate void TryCode(object userData);
public delegate void WaitCallback(object state);
public delegate void TimerCallback(object state);
public delegate void ContextCallback(object state);
......

  17个Action委托,其中包含16个泛型委托:

public delegate void Action();
public delegate void Action<T>(T arg);
public delegate void Action<T1, T2>(T1 arg1, T2 arg2);
public delegate void Action<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3);
......
public delegate void Action<T1,....., T16>(T1 arg1,......, T16 arg16);

  Func委托,允许回调方法返回值:

public delegate TResult Func<TResult>();
public delegate TResult Func<T, TResult>(T arg);
public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);
public delegate TResult Func<T1, T2, T3, TResult>(T1 arg1, T2 arg2, T3 arg3);
......
public delegate TResult Func<T1,....., T16, TResult>(T1 arg1,....., T16 arg16);

实践案例

  这里我将在项目中演示主线程中调用子线程中的值(同样,子线程也可以调用主线程中的值),通过此示例,我们可以进行一些事件的开发。示例代码如下:

class Program
{
    // 申明委托 GetSum,委托修饰符:delegate
    private delegate string del();
    static void Main(string[] args)
    {
        // 定义一个多线程
        Thread thread = new Thread(setStr);
        // 开始执行多线程
        thread.Start();
        // 等待这个线程执行 3S,再去执行下方代码,以确保变量 str 已经被赋值
        Thread.Sleep(3000);
        // 实例化委托
        del _del = getStr;
        // 执行委托并打印出结果
        Console.WriteLine($"获取的字符串:{_del()}");
        Console.ReadLine();
    }
    private static string str="";
    private static void setStr()
    {
        str = "设置的字符串!";
    }
    private static string getStr()
    {
        return str;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值