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

作者:风,停下 时间:2022-10-13 04:43:14 

委托:委托(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");
}

输出结果:

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

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

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

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

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

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

异常信息:

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

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

处理方案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}");
   }

}

输出结果:

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

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

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

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

到这里,委托的介绍我们已经介绍完了,更多相关C# Func 和Action 委托内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

来源:https://blog.csdn.net/weixin_47492910/article/details/122959045

标签:C#,Func,Action,委托
0
投稿

猜你喜欢

  • C#正则表达式大全

    2023-12-04 13:06:37
  • 关于@ConditionalOnProperty的作用及用法说明

    2023-11-24 02:39:19
  • 安卓逆向半次元app逆向分析源码

    2023-07-28 14:36:05
  • Java新特性之Nashorn_动力节点Java学院整理

    2022-07-31 17:18:13
  • C#使用Effects给图片增加阴影效果

    2023-09-09 14:50:18
  • 解析JAVA深度克隆与浅度克隆的区别详解

    2023-11-02 10:57:28
  • Android实现绘制折线图APP代码

    2022-12-10 07:50:02
  • Android RecyclerView实现滑动删除

    2022-11-20 19:50:42
  • Spring中的注解之@Override和@Autowired

    2022-08-07 19:56:47
  • 了解Java线程池执行原理

    2022-10-12 13:00:23
  • Android实现照片墙效果的实例代码

    2023-01-20 16:53:37
  • java 流与 byte[] 的互转操作

    2023-06-26 11:25:46
  • Java执行JS脚本工具

    2022-04-07 08:00:16
  • go打包aar及flutter调用aar流程详解

    2023-06-24 17:39:21
  • C#实现文本转语音功能

    2021-07-07 20:20:54
  • Java I/O 操作及优化详细介绍

    2022-07-30 14:46:42
  • IDEA 2020.2 +Gradle 6.6.1 + Spring Boot 2.3.4 创建多模块项目的超详细教程

    2021-11-08 00:42:36
  • C#获取项目指定目录下文件的方法

    2023-04-19 07:15:26
  • Java实现储存对象并按对象某属性排序的几种方法示例

    2022-05-04 18:05:57
  • Java多线程之同步工具类CyclicBarrier

    2021-10-13 00:24:20
  • asp之家 软件编程 m.aspxhome.com