C#委托的概念与使用方法

news2025/12/14 16:55:07

一、委托的基本概念

  • 委托是一种引用类型,它允许将方法作为参数进行传递。简单来说,委托就像是对方法的引用,可以通过委托来调用对应的方法。

  • 委托具有类型安全性,它会检查方法的签名是否与委托的签名匹配,这有助于避免类型不匹配的错误。

二、委托的声明与使用 

  • 声明委托 :使用 delegate 关键字来声明一个委托,其语法形式为:[访问修饰符] delegate 返回类型 委托名 (参数列表); 。例如:public delegate int MyDelegate(int x, int y); ,这表示声明了一个名为 MyDelegate 的委托,它接受两个整型参数,并返回一个整型值。

  • 实例化委托 :要使用委托,首先需要实例化它。实例化委托时需要指定一个与委托签名匹配的方法。例如:

    public class Program
    {
        public static int Add(int a, int b)
        {
            return a + b;
        }
    
        static void Main(string[] args)
        {
            MyDelegate myDelegate = new MyDelegate(Add);
            int result = myDelegate(2, 3);
            Console.WriteLine(result);  // 输出 5
        }
    }

    在这个例子中,我们声明了一个委托 MyDelegate,然后定义了一个与委托签名匹配的方法 Add。在 Main 方法中,我们实例化了委托 myDelegate,并将其指向 Add 方法,最后通过委托调用了 Add 方法。

  • 匿名方法 :在实例化委托时,还可以使用匿名方法,即无需事先定义一个方法,而是在实例化委托时直接定义方法体。例如:MyDelegate myDelegate = delegate(int x, int y) { return x + y; };这种方式可以在某些简单场景下简化代码。

  • lambda 表达式 :lambda 表达式是匿名方法的更简洁的表示形式,它在语法上更加简洁直观。例如:MyDelegate myDelegate = (x, y) => x + y;这里的 (x, y) => x + y 就是一个 lambda 表达式,它表示接受两个参数 xy,并返回它们的和。

三、系统委托 

  • Action 委托System.Action 是一个无返回值的委托。它可以用于表示不返回任何结果的方法。例如:

    Action<string> printAction = s => Console.WriteLine(s);
    printAction("Hello, World!");

    这个例子中,Action<string> 表示一个接受一个字符串参数且无返回值的委托。我们通过 lambda 表达式定义了 printAction 委托,使其将接收到的字符串打印到控制台。

  • Func 委托System.Func 是一个有返回值的委托。它可以用于表示返回特定类型结果的方法。例如:

    Func<int, int, int> addFunc = (a, b) => a + b;
    int result = addFunc(2, 3);
    Console.WriteLine(result);  // 输出 5
  • Predicate 委托System.Predicate 是一个返回布尔值的委托。它通常用于表示判断条件的方法。例如:

    List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
    Predicate<int> isEven = n => n % 2 == 0;
    List<int> evenNumbers = numbers.FindAll(isEven);
    foreach (int num in evenNumbers)
    {
        Console.WriteLine(num);  // 输出 2 和 4
    }

    在这个例子中,Predicate<int> 表示一个接受一个整型参数并返回一个布尔值的委托。我们通过 lambda 表达式定义了 isEven 委托,使其判断一个整数是否为偶数。然后使用 FindAll 方法将列表中满足条件的元素筛选出来。

四、事件委托 

  • 概念 :事件是基于委托的一种特殊应用,用于在对象之间传递消息。事件委托是定义事件的基础,它规定了事件处理程序的方法签名。

  • 声明事件委托 :通常,事件委托的声明需要结合特定的参数类型,如 EventArgs 及其派生类。例如:public delegate void EventHandler(object sender, EventArgs e);这是 .NET 中一个常见的事件委托声明,其中 sender 表示事件源,e 包含事件相关的数据。

  • 声明事件 :在类中使用 event 关键字来声明事件。例如:

    public class Button
    {
        public event EventHandler Click;
        // 其他代码
    }

    在这个例子中,Button 类声明了一个名为 Click 的事件,它基于 EventHandler 委托。

  • 引发事件 :在适当的时候(如用户点击按钮时),调用事件来通知订阅者。在引发事件时,通常需要创建一个事件数据对象作为参数传递。例如:

protected virtual void OnClick(EventArgs e)
{
    Click?.Invoke(this, e);
}

OnClick 方法用于引发 Click 事件。使用 Click?.Invoke(this, e); 的方式可以安全地调用事件,避免事件为 null 时引发异常。

  • 订阅事件 :其他对象可以通过注册事件处理程序来订阅事件。例如:

    Button button = new Button();
    button.Click += Button_Click;
    
    void Button_Click(object sender, EventArgs e)
    {
        // 处理按钮点击事件的逻辑
    }

    在这段代码中,我们创建了一个 Button 对象,并通过 += 运算符将 Button_Click 方法订阅到 Click 事件上。当按钮被点击时,Button_Click 方法将被调用。

  • 解除订阅 :在不需要再接收事件通知时,可以使用 -= 运算符来解除订阅。例如:button.Click -= Button_Click;

五、委托的多播 

  • 概念 :委托可以将多个方法组合在一起,形成一个调用链,这就是委托的多播特性。当调用多播委托时,它会按照添加的顺序依次调用所有组合的方法。

  • 示例

    public class Program
    {
        public static void Method1()
        {
            Console.WriteLine("Method1 called");
        }
    
        public static void Method2()
        {
            Console.WriteLine("Method2 called");
        }
    
        static void Main(string[] args)
        {
            Action action1 = Method1;
            Action action2 = Method2;
            Action multiCastDelegate = action1 + action2;
            multiCastDelegate();
            // 输出:
            // Method1 called
            // Method2 called
        }
    }

    在这个例子中,我们创建了两个 Action 委托 action1action2,它们分别指向 Method1Method2 方法。然后通过 + 运算符将它们组合成一个多播委托 multiCastDelegate。当调用 multiCastDelegate 时,Method1Method2 会依次被执行。

六、总结 

C# 中的委托是一种强大的机制,它允许将方法作为参数进行传递,并且具有类型安全性。系统委托如 ActionFuncPredicate 提供了方便的预定义委托类型,可以用于各种常见的场景。事件委托则是委托在事件驱动编程中的特殊应用,用于解耦事件源和事件处理者。委托的多播特性使得可以将多个方法组合在一起形成调用链,提供了更大的灵活性。

通过合理使用委托,可以使代码更加模块化、灵活和可维护。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2399022.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

消费者行为变革下开源AI智能名片与链动2+1模式S2B2C商城小程序的协同创新路径

摘要&#xff1a;在信息爆炸与消费理性化趋势下&#xff0c;消费者从被动接受转向主动筛选&#xff0c;企业营销模式面临重构挑战。本文提出开源AI智能名片与链动21模式S2B2C商城小程序的协同创新框架&#xff0c;通过AI驱动的精准触达、链动裂变机制与S2B2C生态赋能&#xff0…

软考 系统架构设计师系列知识点之杂项集萃(78)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之杂项集萃&#xff08;77&#xff09; 第139题 以下关于软件测试工具的叙述&#xff0c;错误的是&#xff08;&#xff09;。 A. 静态测试工具可用于对软件需求、结构设计、详细设计和代码进行评审、走查和审查 B. 静…

如何解决MySQL Workbench中的错误Error Code: 1175

错误描述&#xff1a; 在MySQL Workbench8.0中练习SQL语句时&#xff0c;执行一条update语句&#xff0c;总是提示如下错误&#xff1a; Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY columnTo disab…

Docker 镜像(或 Docker 容器)中查找文件命令

在 Docker 镜像&#xff08;或 Docker 容器&#xff09;中运行如下两个命令时&#xff1a; cd / find . -name generate.py它们的含义如下&#xff0c;我们来一行一行详细拆解&#xff0c;并结合例子讲解&#xff1a; ✅ 第一行&#xff1a;cd / ✅ 含义 cd 是“change dire…

MySQL进阶篇(存储引擎、索引、视图、SQL性能优化、存储过程、触发器、锁)

MySQL进阶篇 存储引擎篇MySQL体系结构存储引擎简介常用存储引擎简介存储引擎的选择 索引篇索引简介索引结构(1)BTree索引(2)hash索引 索引分类索引语法SQL性能分析指标(1)SQL执行频率(2)慢查询日志(3)profile详情(4)explain或desc执行计划 索引使用引起索引的失效行为SQL提示覆…

BugKu Web渗透之game1

启动场景&#xff0c;打开网页如下&#xff1a; 是一个游戏。 步骤一&#xff1a; 右键查看源代码也没有发现异常。 步骤二&#xff1a; 点击开始游戏来看看。 结果他是这种搭高楼的游戏。我玩了一下子&#xff0c;玩到350分就game over。 之后就显示游戏结束&#xff0c;如…

Axure设计案例——科技感渐变柱状图

想让你的数据展示瞬间脱颖而出&#xff0c;成为众人瞩目的焦点吗&#xff1f;快来看看这个 Axure 设计的科技感渐变柱状图案例&#xff01;科技感设计风格以炫酷的渐变色彩打破传统柱状图的单调&#xff0c;营造出一种令人惊叹的视觉盛宴。每一个柱状体都仿佛蕴含着无限能量&am…

互联网大厂智能体平台体验笔记字节扣子罗盘、阿里云百炼、百度千帆 、腾讯元器、TI-ONE平台、云智能体开发平台

互联网大厂 字节扣子、阿里云百炼、百度千帆 、腾讯元器、TI-ONE平台、云智能体开发平台 体验 开始动手 了解 智能体&#xff0c;发现已经落后时代太远 光头部互联网大厂对开 公开的平台就已经这么多&#xff0c;可以学习和了解&#xff0c;相关的信息 整理了对应的平台地址…

深入解析ReactJS中JSX的底层工作原理

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…

NodeMediaEdge任务管理

NodeMediaEdge任务管理 简介 NodeMediaEdge是一款部署在监控摄像机网络前端中&#xff0c;拉取Onvif或者rtsp/rtmp/http视频流并使用rtmp/kmp推送到公网流媒体服务器的工具。 在未使用NodeMediaServer的情况下&#xff0c;或是对部分视频流需要单独推送的需求&#xff0c;也可…

SpringBoot集成第三方jar的完整指南

原文地址&#xff1a;https://blog.csdn.net/weixin_43826336/article/details/141640152?ops_request_misc%257B%2522request%255Fid%2522%253A%25227d4118ef2d572ba4428caf83f1d2bb28%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id7d4118…

前端基础之《Vue(18)—路由知识点》

一、两种路由模式 1、hash路由 &#xff08;1&#xff09;url中有#号&#xff0c;背后是监听onhashchange事件 &#xff08;2&#xff09;hash路由部署上线不会出现404问题&#xff0c;背后是基于history api实现的 2、history路由 &#xff08;1&#xff09;url中没有#号 &a…

014校园管理系统技术解析:构建智慧校园管理平台

校园管理系统技术解析&#xff1a;构建智慧校园管理平台 在教育信息化快速发展的当下&#xff0c;校园管理系统成为提升学校管理效率、优化校园服务的重要工具。该系统集成院校管理、投票管理等多个核心模块&#xff0c;面向管理员、用户和院内管理员三种角色&#xff0c;通过…

SQLite详细解读

一、SQLite 是什么&#xff1f; SQLite 是一个嵌入式关系型数据库管理系统&#xff08;RDBMS&#xff09;。它不是像 MySQL 或 PostgreSQL 那样的客户端-服务器数据库引擎&#xff0c;而是一个自包含的、无服务器的、零配置的、事务性的 SQL 数据库引擎。 核心特点 嵌入式/库…

LRC and VIP

//首先排除所有数相等的情况,再把最大值放在一个组&#xff0c;那么最大值的gcd就等于其本身&#xff0c;再判断剩下的gcd是否等于最大值就可以了 #include<bits/stdc.h> using namespace std;const int N1e3100; int a[N]; map<int,int>mapp; int main(){int t;ci…

Python趣学篇:Pygame重现经典打砖块游戏

名人说&#xff1a;路漫漫其修远兮&#xff0c;吾将上下而求索。—— 屈原《离骚》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 专栏介绍&#xff1a;《Python星球日记》 目录 一、游戏背景与技术选型1. 打砖块游戏…

【Netty系列】Reactor 模式 2

目录 流程图说明 关键流程 以下是 Reactor 模式流程图&#xff0c;结合 Netty 的主从多线程模型&#xff0c;帮助你直观理解事件驱动和线程分工&#xff1a; 流程图说明 Clients&#xff08;客户端&#xff09; 多个客户端&#xff08;Client 1~N&#xff09;向服务端发起连…

TomatoSCI分析日记:数据分析为什么用csv不用excel

其实并不是多余&#xff0c;虽然看到的内容是一样的&#xff0c;但是相比excel文件&#xff0c;csv文件没这么多繁文缛节&#xff0c;效率更高。 1.csv更干净 csv本质是纯文本&#xff0c;只有你看到的数据&#xff0c;没有花里胡哨的单元格格式、颜色、批注等隐藏信息&#…

HTTP协议完全指南:从请求响应到HTTPS安全机制

文章目录 一、HTTP协议中的基本概念1.HTTP协议介绍&#xff08;1&#xff09;协议&#xff08;2&#xff09;传输&#xff08;3&#xff09;超文本 2.统一资源定位符&#xff08;URL&#xff09; 二、HTTP协议中的请求和响应1.HTTP客户端请求消息&#xff08;1&#xff09;请求…

设计模式——状态设计模式(行为型)

摘要 状态设计模式是一种行为型设计模式&#xff0c;核心在于允许对象在内部状态改变时改变行为。它通过状态对象封装不同行为&#xff0c;使状态切换灵活清晰。该模式包含环境类、抽象状态类和具体状态类等角色&#xff0c;具有避免大量分支判断、符合单一职责和开闭原则等特…