在 C# 9 中使用 foreach 扩展
在 C# 9 中,foreach 循环可以使用扩展方法。在本文中,我们将通过例子回顾 C# 9 中如何扩展 foreach 循环。
代码演示
下面是一个对树形结构进行深度优先遍历的示例代码:
using System;
using System.Collections.Generic;
namespace Example
{
class TreeNode
{
public int Value { get; set; }
public List<TreeNode> Children { get; set; }
public TreeNode(int value)
{
Value = value;
Children = new List<TreeNode>();
}
}
static class TreeExtensions
{
public static IEnumerable<TreeNode> DepthFirst(this TreeNode root)
{
yield return root;
foreach (var child in root.Children.SelectMany(DepthFirst))
{
yield return child;
}
}
}
class Program
{
static void Main(string[] args)
{
var root = new TreeNode(1);
root.Children.Add(new TreeNode(2));
root.Children.Add(new TreeNode(3));
root.Children[0].Children.Add(new TreeNode(4));
root.Children[0].Children.Add(new TreeNode(5));
foreach (var node in root.DepthFirst())
{
Console.WriteLine(node.Value);
}
// Outputs: 1 2 4 5 3
}
}
}
在这个示例代码中,我们在 TreeNode 类中定义了一个值属性和一个存储子节点的列表属性。我们还在 TreeExtensions 类中定义了一个 DepthFirst 扩展方法,该方法使用 yield return 语句来返回树形结构的深度优先遍历结果。
在 Main 方法中,我们创建了一个树形结构,然后使用 foreach 循环来遍历树形结构的深度优先遍历结果。
之所以使用扩展方法往往是因为,我们可以在不修改 TreeNode 类的情况下,为 TreeNode 类添加新的功能。
那么接下来我们希望在 C# 9 中默认为 TreeNode 类添加 DepthFirst 行为,这样我们就可以直接使用 foreach 循环来遍历树形结构的深度优先遍历结果了。
C# 9 中的 foreach 扩展
在 C# 9 中,我们可以使用 foreach 扩展来实现上面的需求。我们只需要在 TreeNode 类中添加一个 GetEnumerator 方法,该方法返回一个实现了 IEnumerable 接口的对象即可。
static class TreeExtensions
{
public static IEnumerable<TreeNode> DepthFirst(this TreeNode root)
{
yield return root;
foreach (var child in root.Children.SelectMany(DepthFirst))
{
yield return child;
}
}
public static IEnumerator<TreeNode> GetEnumerator(this TreeNode root)
{
return root.DepthFirst().GetEnumerator();
}
}
在上面的代码中,我们在 TreeNode 类中添加了一个 GetEnumerator 方法,该方法返回一个实现了 IEnumerable 接口的对象。这个对象就是我们在 DepthFirst 方法中使用 yield return 语句返回的结果。
现在我们可以直接使用 foreach 循环来遍历树形结构的深度优先遍历结果了。
foreach (var node in root)
{
Console.WriteLine(node.Value);
}
总结
在 C# 9 中,我们可以使用 foreach 扩展来为类添加新的行为。在上面的示例代码中,我们为 TreeNode 类添加了 DepthFirst 行为,这样我们就可以直接使用 foreach 循环来遍历树形结构的深度优先遍历结果了。
参考资料
- Extension GetEnumerator support for foreach loops[1]
- 本文作者: newbe36524
- 本文链接: https://www.newbe.pro/ChatAI/0x013-Extension-foreach-in-csharp-9/
- 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
参考资料
[1]
Extension GetEnumerator support for foreach loops: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/extension-getenumerator?WT.mc_id=DX-MVP-5003606
在 C# 9 中使用 foreach 扩展的更多相关文章
- 如何正确看待Linq的DistinctBy扩展和ForEach扩展
在微软标准的Linq中,并没有DistinctBy扩展和ForEach扩展,但在平时使用工作中却又经常需要使用到这两个功能,照理来说,微软在Linq中应该包含这两个扩展才对,可事实上为什么并没有呢?本 ...
- EntityFramework 中支持 BulkInsert 扩展
本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. 前言 很显然,你应该不至于使用 EntityFramework 直接插入 10W 数据到数据库中,那 ...
- javascript中的数组扩展(一)
javascript中的数组扩展(一) 随着学习的深入,发现需要学习的关于数组的内容也越来越多,后面将会慢慢归纳,有的是对前面的强化,有些则是关于前面的补充. 一.数组的本质 数组是按照次序排 ...
- EntityFramework中支持BulkInsert扩展(转载)
前言 很显然,你应该不至于使用 EntityFramework 直接插入 10W 数据到数据库中,那可能得用上个几分钟.EntityFramework 最被人诟病的地方就是它的性能,处理大量数据时的效 ...
- 浅析Thinkphp框架中运用phprpc扩展模式
浅析Thinkphp框架中应用phprpc扩展模式 这次的项目舍弃了原来使用Axis2做web服务端的 方案,改用phprpc实现,其一是服务端的thinkphp已集成有该模式接口,其二是phprpc ...
- .NET系统开发过程中积累的扩展方法
分享.NET系统开发过程中积累的扩展方法 .NET 3.5提供的扩展方法特性,可以在不修改原类型代码的情况下扩展它的功能.下面分享的这些扩展方法大部分来自于Code Project或是Stacko ...
- EntityFramework中支持BulkInsert扩展
EntityFramework中支持BulkInsert扩展 本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. 前言 很显然,你应该不至于使用 Ent ...
- JS中的forEach、$.each、map方法推荐
下面小编就为大家带来一篇JS中的forEach.$.each.map方法推荐.小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 orEach是ECMA5中Array新方法中最 ...
- 集合中的 for-Each循环
数组的加强型的for-Each循环很简单,我们再来看一下集合中的for-Each 循环又是怎么样的.我们都知道集合中的遍历都是通过迭代(iterator)完成的.也许有人说,也可以按照下面的方式来遍 ...
- PHP中的IMAP扩展简单入门
对于邮件处理来说,大家比较熟悉的应该是 POP3 . SMTP 这类的协议,而今天我们介绍的 IMAP 其实也是非常常用的一种邮件处理协议.它和 POP3 比较类似,都是以接收处理邮件为主.不过相对于 ...
随机推荐
- grpc中的拦截器
0.1.索引 https://waterflow.link/articles/1665853719750 当我们编写 HTTP 应用程序时,您可以使用 HTTP 中间件包装特定于路由的应用程序处理程序 ...
- AIR32F103(三) Linux环境基于标准外设库的项目模板
目录 AIR32F103(一) 合宙AIR32F103CBT6开发板上手报告 AIR32F103(二) Linux环境和LibOpenCM3项目模板 AIR32F103(三) Linux环境基于标准外 ...
- SQL生成脚本
右键要生成脚本的数据库 选择task 选择Generate script 选择需要生成脚本的table.view.procedure
- 题解 P2080 增进感情
\(\sf Link\) 爆搜最香了. 感觉有点像01背包(? 对于每件事,我们可以选择干或者不干,如果干就将好感值处理一下,当所有的事都搜完之后,记录最小值\(minn\) . 最终答案就是\(mi ...
- k8s运维之pod排错
k8s运维之pod排错 K8S是一个开源的,用于管理云平台中多个主机上的容器化应用,Kubernetes的目标是让部署容器化变得简单并且高效 K8S的核心优势: 1,基于yaml文件实现容器的自动创建 ...
- Atcoder beginner contest 249 C-Just K(二进制枚举)
题目大意:给你N个字符串,你可以从中选择任意数量的字符串,请统计在你的字串中,相同字母出现次数正好为K次的字母数.数据保证出现的字母都是小写字母. 1≤N≤15 1 ≤K≤N 一开始读题的时候读错了, ...
- Codeforces Round #781(C. Tree Infection)
Codeforces Round #781 C. Tree Infection time limit per test 1 second memory limit per test 256 megab ...
- 面试 考察网络请求HTTP相关知识(第六天!)
01.HTTP 常⻅的状态码有哪些? 1xx 服务器收到请求 2xx 请求成功 --- 200 成功状态码 3xx 重定向 --- 301永久重定向,浏览器 ...
- Go语言核心36讲11
至今为止,我们讲过的集合类的高级数据类型都属于针对单一元素的容器. 它们或用连续存储,或用互存指针的方式收纳元素,这里的每个元素都代表了一个从属某一类型的独立值. 我们今天要讲的字典(map)却不同, ...
- Go语言核心36讲12
作为Go语言最有特色的数据类型,通道(channel)完全可以与goroutine(也可称为go程)并驾齐驱,共同代表Go语言独有的并发编程模式和编程哲学. Don't communicate by ...