做淘宝客没网站怎么做,邯郸事件最新消息新闻,企业网上品牌推广,北京互联网公司招聘信息一、什么是委托
委托就相当于是一个可以存放方法的箱子#xff0c;我们可以通过这个“箱子”调用里面的方法#xff0c;比如我下面的代码#xff1a;
// 0.背景#xff1a;委托定义与方法定义// 创建了一个名为MyDelegate的委托#xff0c;这个委托里面装的函数必须有两个…一、什么是委托委托就相当于是一个可以存放方法的箱子我们可以通过这个“箱子”调用里面的方法比如我下面的代码// 0.背景委托定义与方法定义// 创建了一个名为MyDelegate的委托这个委托里面装的函数必须有两个int类型的参数一个int类型的返回值publicdelegateintMyDelegate(inta,intb);// 创建了一个Add方法需要两个int参数一个int返回值与上面委托要求的相符intAdd(inta,intb){returnab;}// 1.实例化类MyClassmyClassnewMyClass();// 2.实例化委托并且将方法装载到委托中MyDelegatemyDelegate1newMyDelegate(myClass.Add);// 3.调用委托即调用委托这个“箱子里的方法Add(1,2)”intresultmyDelegate1.Invoke(1,2);这里我演示了如何简单的使用委托那么有的同学看到可能会疑惑为什么要使用委托直接调用Add(1,2)函数不就好了吗?为什么要写这么麻烦这个问题困扰着每一个委托初学者其实这个问题非常好但是现在我们先往下学在本文我会告诉大家这个问题的答案。1.1 创建委托的语法创建委托的方法有以下几个① 显示创建委托这是 C# 1.0 引入的最基础方式通过new关键字显式创建委托实例并将目标方法作为构造函数参数。委托类型 委托实例new委托类型(目标方法);// 1. 定义委托类型publicdelegatevoidMyDelegate(stringmessage);// 2. 目标方法静态或实例方法均可publicstaticvoidShowMessage(stringmsg){Console.WriteLine(msg);}// 3. 显式实例化委托MyDelegatedelnewMyDelegate(ShowMessage);del(Hello, 显式实例化委托);// 调用委托② 方法组转换简化方式C# 2.0 引入了方法组转换允许直接将方法名赋值给委托实例编译器自动完成new操作。这是最常用的方式之一。委托类型 委托实例目标方法;// 复用上面的 MyDelegate 委托和 ShowMessage 方法MyDelegatedelShowMessage;// 方法组转换del(Hello, 方法组转换);说明目标方法可以是静态方法直接用类名调用或实例方法需先创建类实例。方法签名参数类型、返回值类型必须与委托完全匹配。③ 匿名方法临时方法C# 2.0 引入了匿名方法允许在创建委托时直接定义方法体无需单独声明命名方法。适合临时使用的简单逻辑。语法委托类型 委托实例delegate(参数列表){// 方法体};示例publicdelegatevoidMyDelegate(stringmessage);MyDelegatedeldelegate(stringmsg){Console.WriteLine(匿名方法msg);};del(Hello, 匿名方法);说明匿名方法可以访问外部变量闭包但需注意变量生命周期。若委托无参数delegate()中的参数列表可省略仅匿名方法支持。④ Lambda 表达式最简洁方式C# 3.0 引入了Lambda 表达式是匿名方法的更简洁语法广泛用于 LINQ、事件处理等场景。语法无参数() { 方法体 }或() 表达式单行可省略大括号有参数(参数1, 参数2) { 方法体 }或参数 表达式单参数可省略括号示例// 1. 无参数委托publicdelegatevoidNoParamDelegate();NoParamDelegatedel1()Console.WriteLine(无参数 Lambda);del1();// 2. 有参数委托单行简化MyDelegatedel2msgConsole.WriteLine(Lambdamsg);del2(Hello, Lambda);// 3. 多行 Lambda需大括号和 returnpublicdelegateintCalcDelegate(inta,intb);CalcDelegatedel3(a,b){intsumab;returnsum;};intresultdel3(10,20);// 结果30说明Lambda 表达式同样支持闭包访问外部变量。编译器会根据委托签名自动推断参数类型若委托是泛型委托如Func/Action则参数类型需显式或由上下文推断。1.2 调用委托的语法① 基础调用Invoke()方法Invoke()是委托类型的实例方法用于显式调用委托所引用的方法。这是最明确的调用方式适合强调 “通过委托调用” 的场景。委托实例.Invoke(参数列表);publicdelegatevoidMyDelegate(stringmessage);publicstaticvoidShowMessage(stringmsg){Console.WriteLine(msg);}// 创建委托实例MyDelegatedelShowMessage;// 使用 Invoke() 调用del.Invoke(Hello via Invoke!);// 输出Hello via Invoke!2. 简化调用直接调用编译器语法糖C# 允许将委托实例直接作为方法名调用编译器会自动将其转换为Invoke()调用。这是最常用的简化语法。语法委托实例(参数列表);示例// 复用上面的委托和方法MyDelegatedelShowMessage;// 直接调用等价于 del.Invoke(...)del(Hello via direct call!);// 输出Hello via direct call!1.2 委托的原理谈到这里我们就可以好好聊聊之前的问题了委托到底是什么① 先想清楚为什么需要委托假设你是一个房东想把房子租出去但你不想自己找租客、签合同、收房租太麻烦了。这时候你会找一个房产中介把 “租房” 这件事委托给中介去做。在编程里方法就像 “租房” 这件事而委托就是 “房产中介”—— 它帮你管理方法的调用让你不用直接和方法打交道。② 委托的本质方法的 “代言人”委托的核心作用是把 “方法” 变成一个可以 “传递、存储、调用” 的 “对象”。用更通俗的话讲委托是一个“方法的代言人”它知道 “要调用哪个方法”“怎么调用这个方法”。委托是一个“类型安全的中介”它只接受 “符合要求的方法”比如参数、返回值要匹配就像中介只接受 “合法的房东”。委托是一个“可以同时干多件事的中介”它可以同时帮你调用多个方法比如中介同时帮你找租客、修房子、收房租。③ 用 “租房” 例子拆解委托的核心功能我们把 “租房” 的流程对应到委托的使用上你就能完全理解了第一步定义 “委托类型”相当于 “中介的服务范围”房东找中介前得先明确 “中介要做什么”比如 “帮我找租客签合同收房租”。在编程里这就是定义委托类型规定 “这个委托能代言什么样的方法”比如参数类型、返回值类型。// 定义一个委托类型租房中介负责处理租房相关的事// 参数是租客名字返回值是租金publicdelegateintRentHouseDelegate(stringtenantName);第二步准备 “要委托的方法”相当于 “房东的具体需求”房东需要明确 “具体要做哪些事”比如找租客FindTenant方法签合同SignContract方法收房租CollectRent方法// 房东的具体方法要委托给中介的事publicclassLandlord{// 找租客返回押金比如1000元publicintFindTenant(stringtenant){Console.WriteLine($帮房东找租客{tenant});return1000;// 押金}// 签合同返回第一个月租金比如3000元publicintSignContract(stringtenant){Console.WriteLine($帮房东和租客{tenant}签合同);return3000;// 首月租金}}第三步创建 “委托实例”相当于 “雇佣中介”房东找到中介把 “找租客”“签合同” 这些事委托给中介绑定方法到委托实例。// 创建房东实例具体的房东LandlordlandlordnewLandlord();// 雇佣中介把找租客方法委托给中介RentHouseDelegateagentlandlord.FindTenant;// 还可以让中介同时干多件事再委托签合同方法agentlandlord.SignContract;4. 第四步调用 “委托”相当于 “让中介干活”现在房东只需要告诉中介 “租客名字”中介就会自动执行所有委托的方法找租客 → 签合同。// 让中介干活处理租客张三的租房事宜inttotalMoneyagent(张三);Console.WriteLine($总共收到钱{totalMoney}元);5. 执行结果中介干的活帮房东找租客张三 帮房东和租客 张三 签合同 总共收到钱3000元 // 注意多播委托只返回最后一个方法的结果签合同的3000元④ 委托的本质总结一句话委托就是一个 “方法的代言人”它帮你管理方法的调用让方法可以像变量一样 “传递、存储、批量调用”。⑤ 为什么不用直接调用方法你可能会问“我直接调用landlord.FindTenant(张三)不行吗为什么要找中介”这就涉及到委托的核心价值解决 “方法不能直接传递” 的问题。比如你写了一个 “按钮” 控件点击按钮时要执行 “用户自定义的方法”但你不知道用户会写什么方法可能是 “打开文件”也可能是 “保存数据”。这时候你就需要一个委托来 “接收” 用户的方法点击时再调用。你写了一个 “排序” 方法需要用户提供 “比较规则”比如按年龄排序还是按姓名排序但你不知道用户的比较规则是什么。这时候你就需要一个委托来 “接收” 用户的比较方法排序时再调用。⑥ 再举一个更简单的例子按钮点击事件这是委托最常见的应用场景你肯定见过// 1. 系统定义了一个委托类型点击事件的代言人publicdelegatevoidEventHandler(objectsender,EventArgse);// 2. 按钮有一个点击事件本质是委托实例button.ClicknewEventHandler(OnButtonClick);// 3. 你写的点击后要执行的方法privatevoidOnButtonClick(objectsender,EventArgse){Console.WriteLine(按钮被点击了);}这里的EventHandler就是委托它帮系统 “记住” 了你要执行的OnButtonClick方法当按钮被点击时系统就调用这个委托从而执行你的方法。核心结论委托的本质其实很简单它是一个 “方法的代言人”让方法可以像变量一样被传递、存储和调用。就像你找中介租房不用自己跑断腿编程里用委托不用直接调用复杂的方法而是让委托帮你搞定。二、系统内置的两个委托在 .NET 框架中Action和Func是最常用的两个内置泛型委托它们由System命名空间提供无需手动定义可直接用于几乎所有委托场景。这两个委托的设计目标是减少自定义委托的数量提高代码复用性和可读性。Action委托无返回值的方法引用Action委托用于封装无返回值的方法即void返回类型。它支持 0 到 16 个输入参数通过泛型参数指定参数类型。1. 基本定义无参数Action用于封装 “无参数、无返回值” 的方法。带参数ActionT1、ActionT1, T2、…、ActionT1, T2, ..., T16用于封装 “带 1~16 个参数、无返回值” 的方法泛型参数T1~T16表示参数类型。2. 示例使用Action委托usingSystem;classProgram{staticvoidMain(){// 1. 无参数 Action封装无参数方法ActionprintHello()Console.WriteLine(Hello, Action!);printHello();// 输出Hello, Action!// 2. 带 1 个参数 Action封装带 1 个参数的方法ActionstringprintMessagemsgConsole.WriteLine($Message:{msg});printMessage(你好世界);// 输出Message: 你好世界// 3. 带 2 个参数 Action封装带 2 个参数的方法Actionstring,intprintInfo(name,age)Console.WriteLine(${name}今年{age}岁);printInfo(张三,25);// 输出张三 今年 25 岁}}Func委托有返回值的方法引用Func委托用于封装有返回值的方法。它支持 0 到 16 个输入参数最后一个泛型参数始终表示返回值类型。1. 基本定义无输入参数仅返回值FuncTResult用于封装 “无参数、返回值类型为TResult” 的方法。带输入参数和返回值FuncT1, TResult、FuncT1, T2, TResult、…、FuncT1, T2, ..., T16, TResult用于封装 “带 1~16 个输入参数、返回值类型为TResult” 的方法前N个泛型参数表示输入参数类型最后一个表示返回值类型。2. 示例使用Func委托usingSystem;classProgram{staticvoidMain(){// 1. 无输入参数返回 int封装无参数、返回 int 的方法FuncintgetRandomNumber()newRandom().Next(1,100);intrandomNumgetRandomNumber();Console.WriteLine($随机数{randomNum});// 输出随机数[1-99的随机数]// 2. 带 1 个输入参数返回 string封装带 1 个参数、返回 string 的方法Funcint,stringnumberToStringnum$数字是{num};stringresult1numberToString(123);Console.WriteLine(result1);// 输出数字是123// 3. 带 2 个输入参数返回 int封装带 2 个参数、返回 int 的方法Funcint,int,intadd(a,b)ab;intsumadd(10,20);Console.WriteLine($和{sum});// 输出和30}}三、Action与Func的核心区别特性Action委托Func委托返回值无返回值void必须有返回值最后一个泛型参数为返回值类型泛型参数仅表示输入参数0~16 个前 N 个为输入参数最后一个为返回值类型0~16 个输入参数适用场景用于 “执行操作”如打印、修改状态用于 “计算结果”如求和、转换类型补充Predicate委托特殊的Func除了Action和Func.NET 还提供了PredicateT委托它是FuncT, bool的 “语法糖”专门用于返回布尔值的条件判断如 “判断元素是否满足条件”。基本定义PredicateT封装 “输入参数为T、返回值为bool” 的方法等价于FuncT, bool。示例使用Predicate委托usingSystem;classProgram{staticvoidMain(){// 检查数字是否为偶数等价于 Funcint, boolPredicateintisEvennumnum%20;Console.WriteLine(isEven(4));// 输出TrueConsole.WriteLine(isEven(5));// 输出False}}学完了这些我们基本上算委托入门了接下来我会带着大家做几个委托实战来巩固这些知识点。