公司动态
泛型委托的使用
1. 什么是委托Delegate定义委托是一种类型安全的函数指针用于封装一个或多个具有相同签名的方法。本质编译器生成的密封类继承自System.MulticastDelegate。作用解耦调用方与实现方。支持回调、事件、LINQ、异步编程等场景。2. 委托的声明与实例化2.1 自定义委托类型csharp// 声明一个委托类型public delegate int BinaryOp(int x, int y);// 实例化BinaryOp add (a, b) a b;int result add(3, 4); // 7### 2.2 使用内置泛型委托 | 委托类型 | 签名示例 | 说明 | | ----------- | ------------------- | -------------------------------- | | Action | Actionstring | 无返回值 | | Func | Funcint,int,int | 有返回值最后一个类型为返回类型 | | Predicate | Predicateint | 返回 bool | csharp Funcint,int,int multiply (x, y) x * y; Predicatestring isEmpty s string.IsNullOrEmpty(s);3. 多播委托Multicast Delegate特点一个委托实例可绑定多个方法调用时按添加顺序执行。返回值仅保留最后一个方法的返回值。Actionlog()Console.Write(A);log()Console.Write(B);log()Console.Write(C);log();// 输出 ABC3.1 移除方法log-()Console.Write(B);// 必须使用相同实例4. 匿名方法与 Lambda 表达式// 匿名方法C# 2.0ActionoldStyledelegate(stringmsg){Console.WriteLine(msg);};// Lambda 表达式C# 3.0ActionstringnewStylemsgConsole.WriteLine(msg);5. 委托与事件Event事件是对委托的封装防止外部直接触发。publicclassButton{publiceventEventHandler?Clicked;// 声明事件publicvoidSimulateClick(){Clicked?.Invoke(this,EventArgs.Empty);// 安全触发}}// 订阅事件varbtnnewButton();btn.Clicked(s,e)Console.Write(Button clicked!);btn.SimulateClick();6. 协变与逆变C# 4.0// 协变返回类型可更具体delegateAnimalGetAnimal();GetAnimalgetDog()newDog();// Dog 继承 Animal// 逆变参数类型可更抽象delegatevoidSetDog(Dogd);SetDogsetAnimal(Animala){};// 接受 Animal7. 委托与异步编程7.1 BeginInvoke / EndInvoke已过时Funcint,int,intadd(a,b)ab;add.BeginInvoke(3,4,ar{intresultadd.EndInvoke(ar);Console.WriteLine(result);},null);7.2 使用 Task推荐Funcint,int,intadd(a,b)ab;Task.Run(()add(3,4)).ContinueWith(tConsole.WriteLine(t.Result));8. 高级技巧8.1 委托链异常处理Actionrisky()thrownewException(Oops!);risky()Console.WriteLine(Safe);foreach(Actiondinrisky.GetInvocationList()){try{d();}catch{/* 记录日志 */}}8.2 表达式树与委托转换ExpressionFuncint,int,intexpr(x,y)xy;Funcint,int,intcompiledexpr.Compile();// 转换为委托9. 性能与最佳实践场景建议说明优先使用Action/Func避免自定义委托类型冗余避免闭包陷阱Lambda 捕获循环变量需复制到局部变量事件命名规范使用OnXxx触发Xxx作为事件名10. 完整示例计算器publicclassCalculator{publicdelegatedoubleOperation(doublea,doubleb);publicstaticdoubleExecute(doublea,doubleb,Operationop)op(a,b);publicstaticvoidRun(){varadd:Operation(x,y)xy;varpower:OperationMath.Pow;Console.WriteLine(Execute(2,3,add));// 5Console.WriteLine(Execute(2,3,power));// 8}}