在 C# 9 中使用 foreach 扩展
阅读原文时间:2023年07月08日阅读:2

在 C# 9 中,foreach 循环可以使用扩展方法。在本文中,我们将通过例子回顾 C# 9 中如何扩展 foreach 循环。

下面是一个对树形结构进行深度优先遍历的示例代码:

using&nbsp;System;using&nbsp;System.Collections.Generic;namespace&nbsp;Example{&nbsp;&nbsp;&nbsp;&nbsp;class&nbsp;TreeNode&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;int&nbsp;Value&nbsp;{&nbsp;get;&nbsp;set;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;List<TreeNode>&nbsp;Children&nbsp;{&nbsp;get;&nbsp;set;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;TreeNode(int&nbsp;value)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Value&nbsp;=&nbsp;value;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Children&nbsp;=&nbsp;new&nbsp;List<TreeNode>();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;class&nbsp;TreeExtensions&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;IEnumerable<TreeNode>&nbsp;DepthFirst(this&nbsp;TreeNode&nbsp;root)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield&nbsp;return&nbsp;root;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;(var&nbsp;child&nbsp;in&nbsp;root.Children.SelectMany(DepthFirst))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield&nbsp;return&nbsp;child;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;class&nbsp;Program&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;void&nbsp;Main(string[]&nbsp;args)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;root&nbsp;=&nbsp;new&nbsp;TreeNode(1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;root.Children.Add(new&nbsp;TreeNode(2));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;root.Children.Add(new&nbsp;TreeNode(3));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;root.Children[0].Children.Add(new&nbsp;TreeNode(4));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;root.Children[0].Children.Add(new&nbsp;TreeNode(5));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;(var&nbsp;node&nbsp;in&nbsp;root.DepthFirst())&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(node.Value);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Outputs:&nbsp;1&nbsp;2&nbsp;4&nbsp;5&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;}}

在这个示例代码中,我们在 TreeNode 类中定义了一个值属性和一个存储子节点的列表属性。我们还在 TreeExtensions 类中定义了一个 DepthFirst 扩展方法,该方法使用 yield return 语句来返回树形结构的深度优先遍历结果。

在 Main 方法中,我们创建了一个树形结构,然后使用 foreach 循环来遍历树形结构的深度优先遍历结果。

之所以使用扩展方法往往是因为,我们可以在不修改 TreeNode 类的情况下,为 TreeNode 类添加新的功能。

那么接下来我们希望在 C# 9 中默认为 TreeNode 类添加 DepthFirst 行为,这样我们就可以直接使用 foreach 循环来遍历树形结构的深度优先遍历结果了。

在 C# 9 中,我们可以使用 foreach 扩展来实现上面的需求。我们只需要在 TreeNode 类中添加一个 GetEnumerator 方法,该方法返回一个实现了 IEnumerable 接口的对象即可。

static&nbsp;class&nbsp;TreeExtensions{&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;IEnumerable<TreeNode>&nbsp;DepthFirst(this&nbsp;TreeNode&nbsp;root)&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield&nbsp;return&nbsp;root;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;(var&nbsp;child&nbsp;in&nbsp;root.Children.SelectMany(DepthFirst))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield&nbsp;return&nbsp;child;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;IEnumerator<TreeNode>&nbsp;GetEnumerator(this&nbsp;TreeNode&nbsp;root)&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;root.DepthFirst().GetEnumerator();&nbsp;&nbsp;&nbsp;&nbsp;}}

在上面的代码中,我们在 TreeNode 类中添加了一个 GetEnumerator 方法,该方法返回一个实现了 IEnumerable 接口的对象。这个对象就是我们在 DepthFirst 方法中使用 yield return 语句返回的结果。

现在我们可以直接使用 foreach 循环来遍历树形结构的深度优先遍历结果了。

foreach&nbsp;(var&nbsp;node&nbsp;in&nbsp;root){&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(node.Value);}

在 C# 9 中,我们可以使用 foreach 扩展来为类添加新的行为。在上面的示例代码中,我们为 TreeNode 类添加了 DepthFirst 行为,这样我们就可以直接使用 foreach 循环来遍历树形结构的深度优先遍历结果了。

参考资料

[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

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章