49、c# 能⽤foreach 遍历访问的对象需满足什么条件?

在 C# 中,要使用 foreach 循环遍历一个对象,该对象必须满足以下条件之一:

1. 实现 IEnumerable 或 IEnumerable 接口

  • 非泛型版本:System.Collections.IEnumerable
csharp 复制代码
public class MyCollection : IEnumerable
{
    private int[] _data = { 1, 2, 3 };

    public IEnumerator GetEnumerator()
    {
        return _data.GetEnumerator();
    }
}
  • 泛型版本:System.Collections.Generic.IEnumerable(推荐)
csharp 复制代码
public class MyCollection<T> : IEnumerable<T>
{
    private List<T> _data = new List<T>();

    public IEnumerator<T> GetEnumerator()
    {
        return _data.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator() // 显式实现非泛型接口
    {
        return GetEnumerator();
    }
}

2. 提供 GetEnumerator() 方法的公共非泛型实现

  • 如果类没有显式实现 IEnumerable,但提供了返回 IEnumerator 的公共方法,foreach 仍可工作:
csharp 复制代码
public class MyCollection
{
    private int[] _data = { 1, 2, 3 };

    public IEnumerator GetEnumerator()
    {
        return _data.GetEnumerator();
    }
}

3. 使用 yield return 自动生成枚举器

  • 编译器会自动为包含 yield return 的方法生成 IEnumerable 实现:
csharp 复制代码
public class MyCollection
{
    public IEnumerable<int> GetItems()
    {
        yield return 1;
        yield return 2;
    }
}

// 使用时:
foreach (var item in new MyCollection().GetItems()) { ... }

4. 数组或字符串(语言内置支持)

  • 数组和字符串即使未显式实现接口,也能直接用 foreach 遍历(编译器特殊处理):
csharp 复制代码
int[] array = { 1, 2, 3 };
foreach (int num in array) { ... } // 合法

string str = "hello";
foreach (char c in str) { ... }    // 合法

关键点总结

  • 必须:对象需提供 GetEnumerator() 方法(通过接口或显式实现)。
  • 推荐:优先使用泛型接口 IEnumerable 以获得类型安全和性能优势。
  • 例外:数组和字符串是语言内置的特殊类型。

示例:完整泛型实现

csharp 复制代码
using System.Collections.Generic;

public class MyList<T> : IEnumerable<T>
{
    private List<T> _items = new List<T>();

    public void Add(T item) => _items.Add(item);

    public IEnumerator<T> GetEnumerator() => _items.GetEnumerator();

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        => GetEnumerator();
}

// 使用:
var list = new MyList<int>();
list.Add(1);
list.Add(2);
foreach (var item in list) { ... } // 正常遍历

通过满足上述条件,任何自定义对象都可以使用 foreach 遍历。

相关推荐
山中月侣42 分钟前
Java多线程编程——基础篇
java·开发语言·经验分享·笔记·学习方法
格林威1 小时前
Baumer高防护相机如何通过YoloV8深度学习模型实现网球运动员和网球速度的检测分析(C#代码UI界面版)
人工智能·深度学习·数码相机·yolo·ui·c#·视觉检测
hixiong1231 小时前
用OpencvSharp编写视频录制工具
opencv·c#·音视频
励志不掉头发的内向程序员2 小时前
STL库——string(类模拟实现)
开发语言·c++
王廷胡_白嫖帝2 小时前
Qt文件压缩工具项目开发教程
java·开发语言·qt
张飞洪2 小时前
C# 13 与 .NET 9 跨平台开发实战:基于.NET 9 与 EF Core 9 的现代网站与服务开发
开发语言·c#·.net
许泽宇的技术分享2 小时前
从零到一构建企业级GraphRAG系统:GraphRag.Net深度技术解析
.net
郝学胜-神的一滴2 小时前
使用C++11改进工厂方法模式:支持运行时配置的增强实现
开发语言·c++·程序人生·设计模式
我是场2 小时前
Android14内核调试 - boot & vendor_boot
java·开发语言·spring boot