百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

你需要了解的C# 语言中的 Lambda 表达式和匿名函数

bigegpt 2025-05-10 20:01 38 浏览

Lambda 表达式和匿名函数是 C# 开发中的基本功能,为我们提供了简洁灵活的代码构造。在这篇文章中,我将讨论 lambda 表达式的基础知识,包括它们的语法、使用场景、最新的 C# 12 功能和其他一些高级功能。

Lambda 表达式基础知识

表达式 lambda

表达式 lambda 遵循一个简单的模式:(input-parameters) => expression。例如,(x) => x * x 将输入值 x 平方。这些 lambda 通常用于各种方案,例如 LINQ 查询、使用 Task.Run() 进行任务计划以及异步编程。

LINQ 查询

// List of integers 
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };

// Using a lambda expression in a LINQ query to filter even numbers
var evenNumbers = numbers.Where(x => x % 2 == 0);

// Output the result
foreach (var number in evenNumbers)
{
Console.WriteLine(number);
}

Lambda 表达式用于从列表中筛选偶数。(x => x % 2 == 0)

任务调度Task.Run()

// Using Task.Run with an expression lambda to execute a task asynchronously 
Task.Run(() => {
// Perform some time-consuming operation
for (int i = 0; i < 5; i++)
{
Console.WriteLine($"Task is running: {i}");
Thread.Sleep(1000); // Simulate some work
}
});

在 的任务调度中,表达式 lambda 用于定义异步运行的代码块。Task.Run()

语句 lambdas

相比之下,语句 lambda 将它们的身体包裹在大括号内:

(input-parameters) => { <sequence-of-statements> }

它们为更复杂的逻辑和执行多个语句提供了一个平台。与表达式 lambda 不同,它们在处理控制流和变量范围方面提供了更大的灵活性。例如,请考虑以下事项:

Action<string> greet = name => { 
string greeting = $"Hello {name}!";
Console.WriteLine(greeting);
};

greet("Niraj");

在这里,lambda greet 接受一个字符串参数,使用该参数构造一个问候消息,然后将其打印到控制台。

Lambda 表达式的输入参数

单一输入参数

Lambda 表达式可以具有单个或多个输入参数。在处理单个输入参数时,语法简洁明了,并为声明提供了可选的括号,从而实现了灵活性和可读性。

可以声明单个参数,也可以不带括号:或 。虽然括号是可选的,但它们有助于提高代码的清晰度和组织性。x => x * x(x) => x * x

多个输入参数

多个参数之间用逗号分隔:。- 显式和隐式类型推断提高了代码的清晰度。(x, y) => x + y

Func<int, int, bool> testForEquality = (x, y) => x == y;

这行简单的代码声明了一个名为 的委托,该委托表示一个函数,该函数采用两个整数参数并返回一个布尔值。该表达式定义了一个匿名函数,如果第一个参数等于第二个参数,则返回该函数,否则返回。testForEquality(x, y) => x == ytruexyfalse

委托类型和转换

Lambda 表达式可以转换为 Action 和 Func 等委托类型,从而有助于创建动态和简洁的代码结构。

// Lambda expression converted to Action delegate 
Action<int> printNumber = x => Console.WriteLine(x);
printNumber(10); // Output: 10

// Lambda expression converted to Func delegate
Func<int, int, int> addNumbers = (x, y) => x + y;
int result = addNumbers(5, 3); // result = 8

Action 委托用于具有 void 返回类型的方法,而 Func 委托则用于返回非 void 值的方法。例如,该表达式举例说明了名为 的 Func 委托的创建,该委托计算其整数参数的平方。Func<int, int> square = x => x * x;square

Action 和 Func 委托类型示例:

// Action delegate example (void return type) 
Action<string> greet = name => Console.WriteLine($"Hello, {name}!");
greet("John"); // Output: Hello, John!

// Func delegate example (non-void return type)
Func<int, int> square = x => x * x;
int squaredValue = square(5); // squaredValue = 25

示例演示:

// Asynchronous programming with lambda expressions 
Task.Run(() => {
// Simulate a time-consuming operation
Thread.Sleep(2000);
Console.WriteLine("Asynchronous task completed!");
});

// LINQ query using lambda expressions
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
var evenNumbers = numbers.Where(x => x % 2 == 0);
foreach (var number in evenNumbers) {
Console.WriteLine(number);
}

Lambda 表达式和元组

要定义元组,只需将其组件的逗号分隔列表括在括号内即可。例如,考虑下面的示例,其中具有三个组件的元组用于将数字序列传达到 lambda 表达式。然后,lambda 将每个值加倍,并返回一个包含相应结果的元组。

Func<(int, int, int), (int, int, int)> doubleThem = ns => (2 * ns.Item1, 2 * ns.Item2, 2 * ns.Item3); 
var numbers = (2, 3, 4);
var doubledNumbers = doubleThem(numbers);
Console.WriteLine($"The set {numbers} doubled: {doubledNumbers}");
// Output:
// The set (2, 3, 4) doubled: (4, 6, 8)

此代码块演示了一个名为 lambda 表达式的用法 ,该表达式将一个元组 作为输入并返回另一个元组。lambda 表达式使用参数将输入元组的每个分量乘以 2 。然后,它构造并返回一个具有双倍值的新元组。在此示例中, 带有值_的元组_将传递给 lambda 表达式,而生成的加倍元组将存储在 中。doubleThem(int, int, int)(int, int, int)nsnumbers(2, 3, 4)doubledNumbers

默认情况下,元组字段被命名为 Item1、Item2 等。但是,可以定义具有命名组件的元组以提高清晰度,如后续示例中所示。

Func<(int n1, int n2, int n3), (int, int, int)> doubleThem = ns => (2 * ns.n1, 2 * ns.n2, 2 * ns.n3); 
var numbers = (2, 3, 4);
var doubledNumbers = doubleThem(numbers);
Console.WriteLine($"The set {numbers} doubled: {doubledNumbers}");

此块详细说明了 C# 中元组组件的命名约定。它定义了另一个 lambda 表达式 ,该表达式将具有_命名组件的元组_作为输入。与前面的示例类似,lambda 表达式使用参数将输入元组的每个命名分量加倍 2 。然后,它构造并返回一个具有双倍值的新元组。doubleThem(int n1, int n2, int n3)ns

错误处理和最佳实践

使用 Lambda 表达式进行错误处理

使用 lambda 表达式时,请务必了解错误处理中的潜在陷阱。常见问题包括 引用异常和不正确的参数类型。

// Example of error handling in a lambda expression 
Func<int, int> divideByZeroSafe = divisor =>
{
try
{
return 10 / divisor;
}
catch (DivideByZeroException ex)
{
// Handle divide by zero error
Console.WriteLine($"Error: {ex.Message}");
return 0;
}
};

// Invoke the lambda expression
int result = divideByZeroSafe(0); // Output: Error: Attempted to divide by zero.

在此示例中,lambda 表达式尝试执行除法运算,但通过捕获它并返回默认值来处理 。divideByZeroSafeDivideByZeroException

编写 Lambda 表达式的最佳实践

请考虑以下准则,

  • 保持 lambda 表达式简洁明了且富有表现力。

  • 避免过于复杂或令人费解的语法。

  • 通过最大限度地减少不必要的分配和计算开销来优化性能。

  • 优先考虑可读性和代码可维护性。

使用 Lambda 表达式的优点

  • **简洁:**与传统方法相比,Lambda 表达式允许紧凑和简洁的代码。

  • **可读性:**它们更清楚地表达了程序员的意图,使代码更易于理解。

  • 灵活性: Lambda 表达式可以作为数据传递,从而在程序中实现动态行为。

  • **改进的 API 设计:**Lambda 表达式有助于创建直观且功能强大的 API。

  • 函数式编程: 它们支持函数式编程范式,如高阶函数和函数组合。

  • **并发和异步编程:**Lambda 表达式简化了定义异步操作的语法,有助于开发并发和可扩展的应用程序。

C# 12 的新功能

Lambda 表达式现在可以具有默认参数,从而增强了其灵活性。

var IncrementBy = (int source, int increment = 1) => source + increment; 

Console.WriteLine(IncrementBy(5)); // 6
Console.WriteLine(IncrementBy(5, 2)); // 7

我们还可以声明带有数组作为参数的 lambda 表达式。params

var arraySum = (params int[] nums) => nums.Sum(); 
int[] array1 = { 2, 3, 4, 5 };
Console.WriteLine(arraySum(2, 3, 4, 5));

lambda 表达式和匿名函数就像方便的快捷方式,使我们的代码更短、更易于理解。我鼓励你继续探索它们在不同情况下是如何工作的。

如果你喜欢我的文章,请给我一个赞!谢谢

相关推荐

当Frida来“敲”门(frida是什么)

0x1渗透测试瓶颈目前,碰到越来越多的大客户都会将核心资产业务集中在统一的APP上,或者对自己比较重要的APP,如自己的主业务,办公APP进行加壳,流量加密,投入了很多精力在移动端的防护上。而现在挖...

服务端性能测试实战3-性能测试脚本开发

前言在前面的两篇文章中,我们分别介绍了性能测试的理论知识以及性能测试计划制定,本篇文章将重点介绍性能测试脚本开发。脚本开发将分为两个阶段:阶段一:了解各个接口的入参、出参,使用Python代码模拟前端...

Springboot整合Apache Ftpserver拓展功能及业务讲解(三)

今日分享每天分享技术实战干货,技术在于积累和收藏,希望可以帮助到您,同时也希望获得您的支持和关注。架构开源地址:https://gitee.com/msxyspringboot整合Ftpserver参...

Linux和Windows下:Python Crypto模块安装方式区别

一、Linux环境下:fromCrypto.SignatureimportPKCS1_v1_5如果导包报错:ImportError:Nomodulenamed'Crypt...

Python 3 加密简介(python des加密解密)

Python3的标准库中是没多少用来解决加密的,不过却有用于处理哈希的库。在这里我们会对其进行一个简单的介绍,但重点会放在两个第三方的软件包:PyCrypto和cryptography上,我...

怎样从零开始编译一个魔兽世界开源服务端Windows

第二章:编译和安装我是艾西,上期我们讲述到编译一个魔兽世界开源服务端环境准备,那么今天跟大家聊聊怎么编译和安装我们直接进入正题(上一章没有看到的小伙伴可以点我主页查看)编译服务端:在D盘新建一个文件夹...

附1-Conda部署安装及基本使用(conda安装教程)

Windows环境安装安装介质下载下载地址:https://www.anaconda.com/products/individual安装Anaconda安装时,选择自定义安装,选择自定义安装路径:配置...

如何配置全世界最小的 MySQL 服务器

配置全世界最小的MySQL服务器——如何在一块IntelEdison为控制板上安装一个MySQL服务器。介绍在我最近的一篇博文中,物联网,消息以及MySQL,我展示了如果Partic...

如何使用Github Action来自动化编译PolarDB-PG数据库

随着PolarDB在国产数据库领域荣膺桂冠并持续获得广泛认可,越来越多的学生和技术爱好者开始关注并涉足这款由阿里巴巴集团倾力打造且性能卓越的关系型云原生数据库。有很多同学想要上手尝试,却卡在了编译数据...

面向NDK开发者的Android 7.0变更(ndk android.mk)

订阅Google官方微信公众号:谷歌开发者。与谷歌一起创造未来!受Android平台其他改进的影响,为了方便加载本机代码,AndroidM和N中的动态链接器对编写整洁且跨平台兼容的本机...

信创改造--人大金仓(Kingbase)数据库安装、备份恢复的问题纪要

问题一:在安装KingbaseES时,安装用户对于安装路径需有“读”、“写”、“执行”的权限。在Linux系统中,需要以非root用户执行安装程序,且该用户要有标准的home目录,您可...

OpenSSH 安全漏洞,修补操作一手掌握

1.漏洞概述近日,国家信息安全漏洞库(CNNVD)收到关于OpenSSH安全漏洞(CNNVD-202407-017、CVE-2024-6387)情况的报送。攻击者可以利用该漏洞在无需认证的情况下,通...

Linux:lsof命令详解(linux lsof命令详解)

介绍欢迎来到这篇博客。在这篇博客中,我们将学习Unix/Linux系统上的lsof命令行工具。命令行工具是您使用CLI(命令行界面)而不是GUI(图形用户界面)运行的程序或工具。lsoflsof代表&...

幻隐说固态第一期:固态硬盘接口类别

前排声明所有信息来源于网络收集,如有错误请评论区指出更正。废话不多说,目前固态硬盘接口按速度由慢到快分有这几类:SATA、mSATA、SATAExpress、PCI-E、m.2、u.2。下面我们来...

新品轰炸 影驰SSD多款产品登Computex

分享泡泡网SSD固态硬盘频道6月6日台北电脑展作为全球第二、亚洲最大的3C/IT产业链专业展,吸引了众多IT厂商和全球各地媒体的热烈关注,全球存储新势力—影驰,也积极参与其中,为广大玩家朋友带来了...