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

相关推荐
cmpxr_1 小时前
【C】局部变量和全局变量及同名情况
c语言·开发语言
小碗羊肉1 小时前
【从零开始学Java | 第三十一篇下】Stream流
java·开发语言
aq55356002 小时前
Laravel10.x重磅升级,新特性一览
android·java·开发语言
报错小能手2 小时前
ios开发方向——swift错误处理:do/try/catch、Result、throws
开发语言·学习·ios·swift
网域小星球3 小时前
C 语言从 0 入门(十七)|结构体指针 + 动态内存 + 文件综合实战
c语言·开发语言·文件操作·结构体指针·动态内存·综合项目
gihigo19983 小时前
嵌入式幼儿园刷卡系统 (C#实现)
c#
qq_454245033 小时前
通用引用管理框架
数据结构·架构·c#
aq55356003 小时前
三大编程语言深度对比:C# vs 易语言 vs 汇编
开发语言·汇编·c#
独特的螺狮粉3 小时前
云隙一言:鸿蒙Flutter框架 实现的随机名言应用
开发语言·flutter·华为·架构·开源·harmonyos
光泽雨3 小时前
c# 文件编译的过程
开发语言·c#