C#关于Func和Action委托的介绍

  • Post author:
  • Post category:其他


委托:委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。

委托(Delegate)特别用于实现事件和回调方法。所有的委托(Delegate)都派生自 System.Delegate 类。



1.Action委托

没有返回值,可以不包含参数

(1)声明委托、定位委托事件、向委托添加事件、执行委托

/// <summary>
/// 不包含参数
/// </summary>
private event Action Action_0;
/// <summary>
/// 包含一个参数
/// </summary>
private event Action<int> Action_1;
/// <summary>
/// 包含两个参数
/// </summary>
private event Action<int, double> Action_2;
/// <summary>
/// 包含三个参数
/// </summary>
private event Action<int, double, string> Action_3;

/// <summary>
/// 定义没有参数委托的事件
/// </summary>
private void Fun_0()
{
    Console.WriteLine("没有参数");
}
/// <summary>
/// 定义包含一个参数委托的事件
/// </summary>
private void Fun_1(int nInt)
{
    Console.WriteLine($"包含一个参数:{nInt}");
}
/// <summary>
/// 定义包含两个参数委托的事件
/// </summary>
private void Fun_2(int nInt, double dDouble)
{
    Console.WriteLine($"包含两个参数,参数值:{nInt}{dDouble}");
}
/// <summary>
/// 定义包含三个参数委托的事件
/// </summary>
private void Fun_3(int nInt, double dDouble, string str)
{
    Console.WriteLine($"包含三个参数,参数值:{nInt}{dDouble}{str}");
}


//点击事件
private void btn_Click(object sender, EventArgs e)
{
    //向委托添加事件
    Action_0 += Fun_0;
    Action_1 += Fun_1;
    Action_2 += Fun_2;
    Action_3 += Fun_3;

    //执行委托
    Action_0.Invoke();
    Action_1.Invoke(666);
    Action_2.Invoke(666,888.0);
    Action_3.Invoke(666,888,"Hello World");
}

输出结果:

在这里插入图片描述

由于btn_Click为点击事件,点击第二次(第二次点击会再次向委托添加事件)的数据结果如下:

在这里插入图片描述

因此,向委托添加事件时,一个事件仅添加一次即可,若进行多次添加则调用委托时会将添加进入委托的所有事件进行调用,无论该事件是否已添加都会进行调用,故做如下处理(在构造函数中或在程序启动时添加委托事件):

在这里插入图片描述

上图中委托调用时提示波浪线,因为是委托在调用时可能未添加事件,将会抛出:未将对象引用设置到对象的实例的异常信息,

异常信息:

在这里插入图片描述

故调用时进行异常处理或做如下处理:

处理方案1:

private void button1_Click(object sender, EventArgs e)
{
    Action_0?.Invoke();
    Action_1?.Invoke(666);
    Action_2?.Invoke(666, 888.0);
    Action_3?.Invoke(666, 888, "Hello World");
}

处理方案2

//执行委托
private void button1_Click(object sender, EventArgs e)
{
    try
    {
        Action_0.Invoke();
        Action_1.Invoke(666);
        Action_2.Invoke(666, 888.0);
        Action_3.Invoke(666, 888, "Hello World");
    }
    catch (Exception ex)
    {
        MessageBox.Show("调用出现异常", "提示");
    }
}

此时,我们已经学会了Action委托的简单使用,这时会有人考虑到,我想调用完返回信息Action委托并没有返回,会限制我们的使用,不要着急,我们系统已经帮我们准备了一个现成的委托类型Func,下面我们对Func做个介绍。



2.Func委托

话不多说,上代码,以下我们定义了包含两个参数int和double,返回值为string类型的Func委托,并添加了两个事件Fun_1和Fun_2:

public partial class Form1 : Form
{

    /// <summary>
    /// 包含两个参数int和double,返回值为string类型委托
    /// </summary>
    private event Func<int, double, string> TestFunc;

    /// <summary>
    /// 定义委托的事件
    /// </summary>
    private string Fun_1(int nInt, double dDouble)
    {
        Console.WriteLine($"参数值:{nInt}{dDouble}");
        return "事件:Fun_1";
    }
    /// <summary>
    /// 定义委托的事件
    /// </summary>
    private string Fun_2(int nInt, double dDouble)
    {
        Console.WriteLine($"参数值:{nInt}{dDouble}");
        return "事件:Fun_2";
    }

    /// <summary>
    /// 窗体构造函数
    /// </summary>
    public Form1()
    {
        InitializeComponent();
        InitAction();
    }

    //向委托添加事件
    private void InitAction()
    {
        TestFunc += Fun_1;
        TestFunc += Fun_2;
    }

    //执行委托
    private void button1_Click(object sender, EventArgs e)
    {
        var result = TestFunc?.Invoke(888, 10);
        Console.WriteLine($"返回结果:{result}");
    }

}

输出结果:

在这里插入图片描述


从输出结果不难看出向委托添加多个事件(委托的多播或组播),委托包含返回值时,仅得到最后向委托添加的事件(方法)的返回值,所以在使用有返回值时必须注意这一点。

以下为先添加Fun_2后添加Fun_1的返回结果:

在这里插入图片描述

到这里,委托的介绍我们已经介绍完了,如果您看了觉得有用记得点赞哟。



版权声明:本文为weixin_47492910原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。