首页 > 编程语言 >学懂C#编程:常用高级技术——委托(Delegate)应用场景——委托与Lambda表达式的结合使用详解

学懂C#编程:常用高级技术——委托(Delegate)应用场景——委托与Lambda表达式的结合使用详解

时间:2024-06-23 11:56:57浏览次数:24  
标签:Task Console 委托 C# void 学懂 表达式 Lambda

        在C#中,委托与Lambda表达式的结合使用是现代编程实践中的一个重要且强大的特性,它极大地提高了代码的简洁性和可读性。下面将详细讲解这两个概念如何协同工作,以及如何在实际编程中有效利用它们。

委托基础

        委托是C#中的一种引用类型,它允许封装一个方法的引用。你可以把它想象成一个可以存储和调用方法的变量。委托定义了方法的签名,包括返回类型、参数数量、参数类型等。

Lambda表达式基础

        Lambda表达式是一种编写内联匿名函数的方法,它提供了一种简洁的语法来定义方法。Lambda表达式由输入参数列表、箭头符号=>函数体组成。它在功能上等同于匿名方法,但语法更加紧凑和直观。

 

委托与Lambda结合使用

委托和Lambda表达式结合使用,可以简化代码,特别是在处理事件、LINQ查询、异步操作回调等场景中。

1. 直接赋值给委托变量
public delegate void MyDelegate(int x);

class Program
{
    static void Main(string[] args)
    {
        MyDelegate myDel = x => Console.WriteLine(x * x);
        myDel(5); // 输出25
    }
}

        在这个例子中,我们定义了一个委托类型MyDelegate,然后直接用一个Lambda表达式创建并赋值给myDel变量。Lambda表达式(x => Console.WriteLine(x * x))接受一个整数参数x,并打印其平方。

2. 作为方法参数
public static void ProcessNumbers(int[] numbers, Func<int, int> operation)
{
    foreach (var num in numbers)
    {
        Console.WriteLine(operation(num));
    }
}

class Program
{
    static void Main(string[] args)
    {
        int[] nums = { 1, 2, 3, 4, 5 };
        ProcessNumbers(nums, x => x * 2); // 将每个数字乘以2并打印
    }
}

        这里,ProcessNumbers方法接受一个整数数组和一个Func<int, int>委托(这是C#内置的泛型委托,表示接受一个int参数并返回int值的方法)。我们传入一个Lambda表达式作为第二个参数,实现对数组中每个元素的乘2操作。

3. 在LINQ查询中

        Lambda表达式也是LINQ(Language Integrated Query)查询的核心,它们用于指定查询的筛选、排序等逻辑。

List<int> numbers = new List<int> { 5, 2, 8, 1, 9 };
var evenNumbers = numbers.Where(n => n % 2 == 0); // 使用Lambda表达式筛选偶数
foreach (var num in evenNumbers)
{
    Console.WriteLine(num);
}

在这个LINQ示例中,Where方法接受一个Lambda表达式(n => n % 2 == 0)来筛选出所有偶数。

4. 事件处理中的应用

事件通常与委托结合使用,Lambda表达式可以让事件处理器的注册更加简洁。

using System;

public class Button
{
    public delegate void ClickHandler();
    public event ClickHandler Clicked;
    
    public void SimulateClick()
    {
        Clicked?.Invoke();
    }
}

class Program
{
    static void Main(string[] args)
    {
        Button button = new Button();
        
        button.Clicked += () => Console.WriteLine("Button clicked!");
        
        button.SimulateClick(); // 输出 "Button clicked!"
    }
}

 在这个例子中,Button类有一个事件Clicked,通过Lambda表达式注册了一个事件处理器,当按钮点击事件触发时,会打印出消息。

5. 异步操作的回调

Lambda表达式同样适用于异步编程中的回调处理,使代码更易于理解和维护。

using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        await Task.Run(() =>
        {
            // 模拟长时间运行的任务
            Task.Delay(2000).Wait();
        }).ContinueWith(task =>
        {
            Console.WriteLine("Task completed!");
        });
        
        Console.ReadLine();
    }
}

        这段代码主要展示了如何使用async/await关键字和Task类进行异步编程,目的是让程序在执行耗时操作时不会阻塞主线程,保持界面或控制台的响应性。

  • Task.Run方法在这里启动了一个新任务,它将在后台线程上执行传递给它的代码块。

    • 代码块内的Task.Delay(2000).Wait();模拟了一个长时间运行的操作,实际上只是让当前任务等待2秒。Task.Delay不会占用CPU资源,它只是简单地等待指定的时间间隔。
  • await关键字在此处告诉编译器,主线程应该等待这个任务完成,但在等待期间,主线程不会被阻塞,可以继续执行其他操作(如果有的话)。

  • ContinueWith方法用于在前一个任务(即Task.Run所启动的任务)完成后执行指定的操作。这里的操作是一个Lambda表达式,打印出"Task completed!"。

尽管这个例子使用了ContinueWith方法,现代C#更推荐使用async/await搭配Lambda表达式直接在异步方法内部处理逻辑,但这里展示了Lambda在异步回调中的基本用法。

优势

  • 简洁性:Lambda表达式使得代码更加简洁,减少了代码量,提高了可读性。
  • 即时性:可以在定义委托的同时直接定义其执行逻辑,无需单独定义方法。
  • 功能性:在函数式编程风格中,Lambda表达式配合委托能够轻松实现各种高阶函数操作。

总之,委托与Lambda表达式的结合使用,为C#编程提供了强大的工具,简化了代码结构,提高了开发效率,并使得代码更加现代化和易于维护。

标签:Task,Console,委托,C#,void,学懂,表达式,Lambda
From: https://blog.csdn.net/martian665/article/details/139877842

相关文章

  • 【转载备份】目标检测两种常用的数据集COCO和VOC
     背景:今天跟着我们算法工程师学了几分钟的算法模型训练,她讲到目标检测常用的数据集是COCO和VOC,我不知道啥是数据集,更加不知道这两个是什么,它们有什么用,于是我简单了解了一下子~要解决的问题: 什么是数据集?COCO和VOC是什么?它们分别是什么格式?问题1:什么是数据集?数据集......
  • pkg-config
    一、pkg-configpkg-config是一个命令行工具,主要用于帮助开发者在编译依赖于特定库的软件时,自动获取和设置正确的编译器选项和链接器选项。它的主要作用在于简化编译过程,确保程序能够正确地找到所需的头文件和库文件,尤其是在库文件可能安装在非标准位置的情况下。pkg-config版本......
  • UNIQUE VISION Programming Contest 2024 Summer (AtCoder Beginner Contest 359)
    A-CountTakahashi(abc359A)解题思路遍历判断即可神奇的代码#include<iostream>#include<algorithm>#include<vector>#include<queue>#include<map>#include<set>#include<cstring>usingnamespacestd;#defineendl'\n......
  • Teamcenter 产品配置前操作代码
     importjava.math.BigInteger;importjava.util.HashMap;importjava.util.Iterator;importjava.util.Map;importjava.util.Set;importorg.apache.log4j.Logger;importcom.cfg0.services.internal.strong.configurator.ConfiguratorManagementService;importc......
  • 第4篇:LangChain的数据流与处理机制
    在大数据时代,高效处理和分析海量数据是每个数据工程师和科学家的终极梦想。LangChain作为一种强大的分布式数据处理框架,通过其独特的数据流处理机制,帮助我们实现这一梦想。今天,我们将深入探讨LangChain的数据流处理方式,详细讲解数据流在LangChain中的处理过程,并提供完整的Py......
  • Apache Flink 和 Apache Spark详细介绍、优缺点、使用场景以及选型抉择?
    ApacheFlink和ApacheSpark我该投入谁的怀抱?ApacheFlink简介:ApacheFlink是一个用于分布式流处理和批处理的开源框架。它以实时数据处理和事件驱动的流处理著称,提供高吞吐量和低延迟的处理能力。功能:流处理:Flink可以处理实时数据流,支持低延迟和高吞吐量的流处理......
  • C++入门 vector深度剖析及模拟实现
    目录vector析构函数模拟实现vector赋值拷贝模拟实现vector拷贝构造模拟实现vector构造函数模拟实现类模板的成员函数n个val构造单参数和多参数对象隐式类型转换使用memcpy拷贝问题在上两篇有关vector的模拟实现中,还有构造,拷贝构造,赋值拷贝以及析构函数没有实现,本篇主......
  • [Golang并发]Sync.Mutex
    源码//Copyright2009TheGoAuthors.Allrightsreserved.//UseofthissourcecodeisgovernedbyaBSD-style//licensethatcanbefoundintheLICENSEfile.//Packagesyncprovidesbasicsynchronizationprimitivessuchasmutual//exclusionlocks.......
  • [Golang并发]Sync.map
    sync.Map的实现原理可概括为:通过read和dirty两个字段将读写分离,读取时会先查询read,不存在再查询dirty,写入时则只写入dirty,所以read相当于dirty的缓存。读取read并不需要加锁,而读或写dirty都需要加锁。misses字段统计read被穿透的次数,被穿透指需要读dirty的情......
  • COLA架构初始化DDD项目
    使用COLA脚手架初始化项目实战代码:https://gitee.com/XuXiaoCong/cola-springboot-demoCOLA项目地址:https://github.com/alibaba/COLABiliBili视频创建项目使用COLA脚手架(Maven)创建COLA项目DgroupId:公司/组织名称DartifactId:项目名称Dversion:版本号Dpackage:包路......