在 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 擴充套件來實現上面的需求。我們只需要在 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: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/extension-getenumerator?WT.mc_id=DX-MVP-5003606