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

相关推荐
爱喝阔落的猫14 分钟前
【JVM 07-运行时常量池重要组成部分-StringTable】
开发语言·jvm·python
狐凄19 分钟前
Python实例题:图片批量处理工具
开发语言·python
时光追逐者20 分钟前
.NET初级软件工程师面试经验分享
经验分享·面试·职场和发展·c#·.net·.netcore
上位机付工33 分钟前
C#上位机通过WebApi对接DeepSeek
c#·上位机·plc·webapi
老土豆FUSK1 小时前
C++ 引用的使用
开发语言·c++
code bean1 小时前
【C#】C# 中的 `init`、`readonly` 和 `const` 有什么区别?
开发语言·c#
网小鱼的学习笔记1 小时前
html中的table标签以及相关标签
开发语言·前端·python·html
重整旗鼓~2 小时前
7.索引库操作
java·开发语言
Jay Kay2 小时前
深入解析协程:高并发编程的轻量级解决方案
开发语言·c++·算法
99乘法口诀万物皆可变2 小时前
C#设计模式之AbstractFactory_抽象工厂_对象创建新模式-学习
设计模式·c#·抽象工厂模式