当前位置: 首页 > news >正文

全面解析:C# 委托的实质性应用与优势

有人问C#的委托(Delegate)有什么实质性用途?委托在C#其实是无处不在,那么它具体用在那里呢?。

本文将从委托(Delegate)定义和演变讲起,让大家一目了然。

C#的委托(Delegate)是强类型的函数指针,用于引用方法并允许将方法作为参数传递。随着C#的演变,委托的功能和用途变得越来越强大和灵活。

本文将从C#委托的演变谈起,详细介绍其实质性用途,并通过代码实例加以证明。

委托的演变

C# 1.0: 基本委托

在C# 1.0中,引入了基本的委托概念,使得方法可以作为对象传递。这是实现事件和回调机制的基础。

using System;  public delegate void Notify();  // 声明委托  public class ProcessBusinessLogic  
{  public event Notify ProcessCompleted;  // 使用委托声明事件  public void StartProcess()  {  Console.WriteLine("Process Started!");  // 模拟一些处理任务  System.Threading.Thread.Sleep(3000);  // 处理完成后触发事件  OnProcessCompleted();  }  protected virtual void OnProcessCompleted()  {  ProcessCompleted?.Invoke();  }  
}  class Program  
{  static void Main(string[] args)  {  ProcessBusinessLogic bl = new ProcessBusinessLogic();  bl.ProcessCompleted += Bl_ProcessCompleted;  // 订阅事件  bl.StartProcess();  }  private static void Bl_ProcessCompleted()  {  Console.WriteLine("Process Completed!");  }  
}  
C# 2.0: 匿名方法

C# 2.0引入了匿名方法,使得委托的使用更加灵活,不需要单独定义方法即可实现回调。

using System;  public delegate void Print(int value);  public class Program  
{  public static void Main(string[] args)  {  Print print = delegate(int val) {  Console.WriteLine("Anonymous method: {0}", val);  };  print(100);  }  
}  
C# 3.0: Lambda表达式

C# 3.0进一步引入了Lambda表达式,简化了委托的语法,使得代码更加简洁和易读。

using System;  public delegate void Print(int value);  public class Program  
{  public static void Main(string[] args)  {  Print print = (val) => Console.WriteLine("Lambda expression: {0}", val);  print(200);  }  
}  
C# 4.0及以后: 泛型委托和内置委托类型

随着C#的不断发展,泛型委托和内置委托类型(如ActionFuncPredicate)被引入,进一步增强了委托的功能和灵活性。

using System;  public class Program  
{  public static void Main(string[] args)  {  Action<int> print = val => Console.WriteLine("Action delegate: {0}", val);  print(300);  Func<int, int> square = x => x * x;  Console.WriteLine("Func delegate: {0}", square(5));  Predicate<int> isPositive = x => x > 0;  Console.WriteLine("Predicate delegate: {0}", isPositive(10));  }  
}  

委托的实质性用途

1、简单回调机制

在编写需要回调功能的代码时,委托可以扮演重要角色。例如,当一个方法完成某项任务时,可以通过回调通知调用者。

using System;  public delegate void Notify();  // 声明委托  public class ProcessBusinessLogic  
{  public event Notify ProcessCompleted;  // 使用委托声明事件  public void StartProcess()  {  Console.WriteLine("Process Started!");  // 模拟一些处理任务  System.Threading.Thread.Sleep(3000);  // 处理完成后触发事件  OnProcessCompleted();  }  protected virtual void OnProcessCompleted()  {  ProcessCompleted?.Invoke();  }  
}  class Program  
{  static void Main(string[] args)  {  ProcessBusinessLogic bl = new ProcessBusinessLogic();  bl.ProcessCompleted += Bl_ProcessCompleted;  // 订阅事件  bl.StartProcess();  }  private static void Bl_ProcessCompleted()  {  Console.WriteLine("Process Completed!");  }  
}  

在这个例子中,当StartProcess方法执行完毕时,会通过委托Notify通知订阅者。

2、多播委托

多播委托可以引用多个方法,并且在调用时按顺序调用这些方法。这对于需要依次执行多个处理的场景非常有用。

using System;  public delegate void Notify();  // 声明委托  public class Program  
{  public static void Main(string[] args)  {  Notify notify = Method1;  notify += Method2;  // 订阅多个方法  notify();  }  public static void Method1()  {  Console.WriteLine("Method1 invoked.");  }  public static void Method2()  {  Console.WriteLine("Method2 invoked.");  }  
}  

在这个例子中,notify委托依次调用Method1Method2

3、匿名方法和Lambda表达式

委托可以结合匿名方法和Lambda表达式使用,使代码更加简洁和灵活。

using System;  public delegate void Print(int value);  public class Program  
{  public static void Main(string[] args)  {  Print print = delegate(int val) {  Console.WriteLine("Anonymous method: {0}", val);  };  print(100);  print = (val) => Console.WriteLine("Lambda expression: {0}", val);  print(200);  }  
}  

在这个例子中,使用匿名方法和Lambda表达式定义委托的实现方式,使代码更加简洁。

4、事件处理

委托是事件处理的基础,通过委托可以实现事件的定义和处理。例如,在用户界面编程中,按钮的点击事件处理。

using System;  public class Button  
{  public delegate void ClickHandler(object sender, EventArgs e);  public event ClickHandler Click;  public void OnClick(EventArgs e)  {  Click?.Invoke(this, e);  }  
}  public class Program  
{  public static void Main(string[] args)  {  Button button = new Button();  button.Click += Button_Click;  button.OnClick(EventArgs.Empty);  }  private static void Button_Click(object sender, EventArgs e)  {  Console.WriteLine("Button clicked!");  }  
}  

在这个例子中,Button类定义了Click事件,通过委托ClickHandler处理点击事件。

5、函数式编程

委托允许将函数作为对象处理,使得C#能够支持一定程度的函数式编程。例如,LINQ(Language Integrated Query)大量使用了委托和Lambda表达式。

using System;  
using System.Linq;  
using System.Collections.Generic;  public class Program  
{  public static void Main(string[] args)  {  List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };  List<int> evenNumbers = numbers.Where(n => n % 2 == 0).ToList();  evenNumbers.ForEach(n => Console.WriteLine(n));  }  
}  

在这个例子中,Where方法接受一个委托Func<int, bool>来筛选列表中的偶数。

总结

C#的委托从基本概念到匿名方法,再到Lambda表达式和泛型委托,其演变展示了语言的强大和灵活。

委托在回调、多播、事件处理以及函数式编程中的广泛应用,极大地增强了C#的功能和代码可维护性。

通过本文的示例,可以清晰地看到委托的实质性用途和在现代编程中的重要地位。

希望本文对大家有所收获,大家对委托有什么看法,欢迎留言讨论。

相关文章:

  • windows11子系统Ubuntu 22.04.4子安装图形化界面
  • 在Linux中如何解决程序崩溃的问题
  • linux高级编程(1)
  • 华为Atlas NPU ffmpeg 编译安装
  • cuda与cudnn下载(tensorflow-gpu)
  • 爬虫经典案例之爬取豆瓣电影Top250(方法一)
  • 学习前台开发主要掌握的技能
  • SpringCloud和K8s的区别
  • python从入门到精通4:变量赋值
  • Linux开发讲课7---Linux sysfs文件系统
  • 【设计模式之迭代器模式 -- C++】
  • web安全渗透测试十大常规项(一):web渗透测试之PHP反序列化
  • CentOS 7 内核 3.10 升级 6.5.2 (RPM 直装 + 源码编译)
  • 新建一个 React TypeScript 项目,并使用 Webpack 进行构建和打包
  • Java程序之让气球上升
  • ES6指北【2】—— 箭头函数
  • [译] 理解数组在 PHP 内部的实现(给PHP开发者的PHP源码-第四部分)
  • Android交互
  • go语言学习初探(一)
  • IOS评论框不贴底(ios12新bug)
  • SegmentFault 社区上线小程序开发频道,助力小程序开发者生态
  • text-decoration与color属性
  • Yii源码解读-服务定位器(Service Locator)
  • 买一台 iPhone X,还是创建一家未来的独角兽?
  • 判断客户端类型,Android,iOS,PC
  • 数据结构java版之冒泡排序及优化
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 通信类
  • 小程序button引导用户授权
  • 字符串匹配基础上
  • “十年磨一剑”--有赞的HBase平台实践和应用之路 ...
  • 《TCP IP 详解卷1:协议》阅读笔记 - 第六章
  • 阿里云移动端播放器高级功能介绍
  • 策略 : 一文教你成为人工智能(AI)领域专家
  • ​【C语言】长篇详解,字符系列篇3-----strstr,strtok,strerror字符串函数的使用【图文详解​】
  • ​总结MySQL 的一些知识点:MySQL 选择数据库​
  • (4)(4.6) Triducer
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (javaweb)Http协议
  • (webRTC、RecordRTC):navigator.mediaDevices undefined
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (实测可用)(3)Git的使用——RT Thread Stdio添加的软件包,github与gitee冲突造成无法上传文件到gitee
  • (四)Android布局类型(线性布局LinearLayout)
  • (算法二)滑动窗口
  • .NET/C# 检测电脑上安装的 .NET Framework 的版本
  • .net6+aspose.words导出word并转pdf
  • .Net--CLS,CTS,CLI,BCL,FCL
  • .net图片验证码生成、点击刷新及验证输入是否正确
  • 。Net下Windows服务程序开发疑惑
  • @ohos.systemParameterEnhance系统参数接口调用:控制设备硬件(执行shell命令方式)
  • @RequestMapping处理请求异常
  • @SpringBootApplication 包含的三个注解及其含义
  • [AIGC] 解题神器:Python中常用的高级数据结构
  • [Android]Android开发入门之HelloWorld
  • [Android]一个简单使用Handler做Timer的例子