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 遍历。

相关推荐
橙子199110165 分钟前
说说 Kotlin 中的 Any 与 Java 中的 Object 有何异同?
java·开发语言·kotlin
码农捻旧12 分钟前
JavaScript 性能优化按层次逐步分析
开发语言·前端·javascript·性能优化
我命由我1234512 分钟前
Android 开发问题:Plugin [id: ‘org.jetbrains.kotlin.android‘] was not found
android·java·开发语言·java-ee·kotlin·安卓·android-studio
我是哈哈hh24 分钟前
【Vue3】生命周期 & hook函数 & toRef
开发语言·前端·javascript·vue.js·前端框架·生命周期·proxy模式
傻虎贼头贼脑39 分钟前
day28JS+Node-JS打包工具Webpack
开发语言·前端·javascript·webpack
NEWEVA__zzera221 小时前
关于读取CH584单片机的IO电平出现到的乌龙
c语言·开发语言·单片机
江畔柳前堤1 小时前
PyQt学习系列08-插件系统与模块化开发
运维·开发语言·数据库·python·学习·机器学习·pyqt
Logan Lie1 小时前
使用 C 语言做应用开发的注意事项
c语言·开发语言·边缘计算
曼岛_2 小时前
[Java实战]Spring Boot切面编程实现日志记录(三十六)
java·开发语言·spring boot
Archer1942 小时前
C++——QT 文件操作类
开发语言·qt