在 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 比较类似,都是以接收处理邮件为主.不过相对于 ...
随机推荐
- 华为设备配置ssh-client命令
ssh client first-time enable 开启首次认证功能不对ssh服务器的RSA公钥进行有效性验证 stelnet 10.1.1.2 登陆R2 sys 进入到R2的系统视图 disp ...
- PaddleOCR-EAST
目录 EAST Abstract Train PreProcess Architecture Backbone Neck Head Loss Dice Loss SmoothL1 Loss Infer ...
- 从0搭建vue3组件库:自动化发布、管理版本号、生成 changelog、tag
今天看到一篇文章中提到了一个好用的工具release-it.刚好可以用在我正在开发的vue3组件库.纸上得来终觉浅,绝知此事要躬行,说干就干,下面就介绍如何将release-it应用到实际项目中,让组 ...
- JS 学习笔记(一)常用的字符串去重方法
要求:从输入框中输入一串字符,按回车后输出去重后的字符串 方法一: <body> <input type="text" id="input" ...
- JVM学习笔记——垃圾回收篇
JVM学习笔记--垃圾回收篇 在本系列内容中我们会对JVM做一个系统的学习,本片将会介绍JVM的垃圾回收部分 我们会分为以下几部分进行介绍: 判断垃圾回收对象 垃圾回收算法 分代垃圾回收 垃圾回收器 ...
- go:快速添加接口方法及其实现
问题描述 在大型项目中,通常存在多个模块,模块对外暴露的功能通常是通过接口封装,这样可以明确模块的功能,有效降低模块与模块之间的耦合度,同时模块与模块之间进行合理的组装.接口的实现,有时可能存在多个实 ...
- CSS布局秘籍(2)-6脉神剑
HTML系列: 人人都懂的HTML基础知识-HTML教程(1) HTML元素大全(1) HTML元素大全(2)-表单 CSS系列: CSS基础知识筑基 常用CSS样式属性 CSS选择器大全48式 CS ...
- CSS处理器-Less/Scss
HTML系列: 人人都懂的HTML基础知识-HTML教程 HTML元素大全(1) HTML元素大全(2)-表单 CSS系列: CSS基础知识筑基 常用CSS样式属性 CSS选择器大全48式 CSS布局 ...
- perl中sprintf函数的用法
对于某些字符串,需要输入为特定的格式,通过sprintf可以很方便的完成,不需要专门进行其他处理. 转载 perl中sprintf函数的使用方法.
- mysql删库报错
3.开发人员测试环境删库报错 #解决:在数据库的物理目录中(mysql的data目录),进入要删除的数据库目录,查看是否有文件存在,若存在,使用rm -rf 命令清除:再次执行删除数据库命令即可 [r ...