C#学习笔记--foreach循环是怎么遍历容器的?实战带你弄懂foreach原理

前言

上篇文章我们了解了IEnumerableIEnumeratorC#学习笔记–由浅至深理解IEnumerable和IEnumerator

这篇文章我们来研究foreach循环

foreach原理

foreach循环实际上是通过调用集合的GetEnumerator方法来获取一个枚举器,然后在每次迭代中调用枚举器的MoveNext方法来遍历集合的。当枚举器的MoveNext方法返回false时,表示集合中没有更多元素,循环结束。

也就是说,只要是实现了 IEnumerable 接口,都可以被 foreach 循环遍历。

实现自己的容器

那有了这个理论基础,我们赶紧来自己写一个小容器吧

例子一:数组容器

  1. 先定义一个类,实现IEnumerable接口
public class MyNumbers : IEnumerable<int>
{
    private int[] numbers = new int[] { 1, 2, 3 };

    public IEnumerator<int> GetEnumerator()
    {
        return null;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}
  1. 定义该类的迭代器
public class MyNumbers : IEnumerable<int>
{
    private int[] numbers = new int[] { 1, 2, 3 };

    public IEnumerator<int> GetEnumerator()
    {
        return new MyEnumerator(numbers);
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

public class MyEnumerator : IEnumerator<int>
{
    private int[] numbers;
    private int index = -1;

    public MyEnumerator(int[] numbers)
    {
        this.numbers = numbers;
    }

    public int Current
    {
        get
        {
            return numbers[index];
        }
    }

    object IEnumerator.Current
    {
        get
        {
            return Current;
        }
    }

    public bool MoveNext()
    {
        index++;
        return index < numbers.Length;
    }

    public void Reset()
    {
        index = -1;
    }

    public void Dispose()
    {
        // No resources to dispose
    }
}

在这个例子中,我们创建了两个类:MyNumbersMyEnumerator
MyNumbers类实现了IEnumerable< int >接口,它定义了一个GetEnumerator方法,该方法返回一个实现了IEnumerator< int >接口的对象。
MyEnumerator类实现了IEnumerator< int >接口,它定义了用于遍历序列的方法,例如MoveNextCurrent

我们可以使用下面的代码来遍历这个自定义的迭代器类:

MyNumbers myNumbers = new MyNumbers();
foreach (int number in myNumbers)
{
    Console.WriteLine(number);
}

例子二:Student类

  1. 先定义一个Student类,实现IEnumerable接口
public class Student : IEnumerable
{
    private int id;
    private int age;
    private string name;

    public Student(int id_in, int age_in, string name_in)
    {
        id = id_in;
        age = age_in;
        name = name_in;
    }

    public IEnumerator GetEnumerator()
    {
        return null;
    }
}
  1. 定义该类的迭代器
public class Student : IEnumerable
{
    private int id;
    private int age;
    private string name;

    public Student(int id_in, int age_in, string name_in)
    {
        id = id_in;
        age = age_in;
        name = name_in;
    }

    public IEnumerator GetEnumerator()
    {
        return new StudentEnumerator(this);
    }

    private class StudentEnumerator : IEnumerator
    {
        private Student student;
        private int index = -1;

        public StudentEnumerator(Student student)
        {
            this.student = student;
        }

        public object Current
        {
            get
            {
                switch (index)
                {
                    case 0:
                        return student.id;
                    case 1:
                        return student.age;
                    case 2:
                        return student.name;
                    default:
                        throw new InvalidOperationException();
                }
            }
        }

        public bool MoveNext()
        {
            index++;
            return index < 3;
        }

        public void Reset()
        {
            index = -1;
        }
    }
}

在这个例子中,我们创建了两个类:StudentStudentEnumerator
Student 类实现了 IEnumerable 接口,它定义了一个返回 IEnumerator 对象的 GetEnumerator 方法。
StudentEnumerator 类实现了 IEnumerator 接口,它定义了用于遍历序列的方法,例如 MoveNextCurrent

现在,我们可以使用 foreach 循环来遍历 Student 类的实例了。例如:

Student student = new Student(1, 18, "Alice");
foreach (var item in student)
{
    Console.WriteLine(item);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

就一枚小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值