Skip to content
字数
1055 字
阅读时间
6 分钟

关键接口:IEnumerator, IEnumerable 命名空间:using System. Collections; 可以通过同时继承 IEnumerableIEnumerator 实现其中的方法

Foreach本质

  1. 先获取in后面这个对象的 IEnumerator,会调用对象其中的GetEnumerator方法来获取
  2. 执行得到这个IEnumerator对象中的 MoveNext方法
  3. 只要MoveNext方法的返回值时true 就会去得到Current,然后复制给 item
cs
class CustomList : IEnumerable, IEnumerator
{
    private int[] list;
    //从-1开始的光标 用于表示 数据得到了哪个位置
    private int position = -1;
    public CustomList()
    {
        list = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };
    }
    #region IEnumerable
    public IEnumerator GetEnumerator()
    {
        Reset();
        return this;
    }
    #endregion
    public object Current
    {
        get
        {
            return list[position];
        }
    }
    public bool MoveNext()
    {
        //移动光标
        ++position;
        //是否溢出 溢出就不合法
        return position < list.Length;
    }
    //reset是重置光标位置 一般写在获取 IEnumerator对象这个函数中
    //用于第一次重置光标位置
    public void Reset()
    {
        position = -1;
    }
}
class Program
    {
        static void Main(string[] args)
        {
            CustomList list = new CustomList();
        	foreach (int item in list)
            {
                Console.WriteLine(item);
            }
        }
    }
}

Yield return 语法糖

C#
class CustomList2 : IEnumerable
{
    private int[] list;
    public CustomList2()
    {
        list = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };
    }
    public IEnumerator GetEnumerator()
    {
        for (int i = 0; i < list.Length; i++)
        {
            //yield关键字 配合迭代器使用
            //可以理解为 暂时返回 保留当前的状态 一会还会在回来
            yield return list[i];
        }
        //yield return list[0];
        //yield return list[1];
        //yield return list[2];
        //yield return list[3];
        //yield return list[4];
        //yield return list[5];
        //yield return list[6];
        //yield return list[7];
    }
}

用 yield return 语法糖为泛型类实现迭代器

C#
class CustomList<T> : IEnumerable
{
	private T[] array;
	public CustomList(params T[] array)
	{
		this.array = array;
	}
	public IEnumerator GetEnumerator()
	{
		for (int i = 0; i < array.Length; i++)
		{
			yield return array[i];
		}
	}
}
class Program
    {
        static void Main(string[] args)
        {
            CustomList<string> list2 = new CustomList<string>("123","321","333","555");
            foreach (string item in list2)
            {
                Console.WriteLine(item);
            }
        }
    }
}

补充:yield return

yield return是C#中的一个关键字 ,用于简化迭代器的实现。它允许你在一个方法中逐步返回数据,而不需要显式地管理状态。使用yield return返回的数据可以用于多种场景,主要是为了简化集合的迭代和生成。 主要用途

  1. 简化迭代器的实现: • yield return可以让你轻松地实现IEnumerable接口,而不需要显式地管理IEnumerator的状态。
  2. 延迟执行: • yield return实现的迭代器是延迟执行的,这意味着只有在实际迭代时才会生成数据。这对于处理大数据集或需要懒加载的场景非常有用。
  3. 提高代码可读性: • 使用yield return可以使代码更加简洁和易读,减少了手动管理状态的复杂性。

以下是一些使用yield return的示例,展示了它的不同用途。

示例1 :简单的迭代器
C#
using System;
using System.Collections;
using System.Collections.Generic;

public class SimpleCollection : IEnumerable<int>
{
    private int[] numbers = { 1, 2, 3, 4, 5 };

    public IEnumerator<int> GetEnumerator()
    {
        foreach (int number in numbers)
        {
            yield return number;
        }
    }

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

class Program
{
    static void Main()
    {
        SimpleCollection collection = new SimpleCollection();
        foreach (int number in collection)
        {
            Console.WriteLine(number);
        }
    }
}
示例 2:生成斐波那契数列
C#
using System;
using System.Collections.Generic;

public class FibonacciSequence
{
    public static IEnumerable<int> GetFibonacciNumbers(int count)
    {
        int a = 0, b = 1;
        for (int i = 0; i < count; i++)
        {
            yield return a;
            int temp = a;
            a = b;
            b = temp + b;
        }
    }
}

class Program
{
    static void Main()
    {
        foreach (int number in FibonacciSequence.GetFibonacciNumbers(10))
        {
            Console.WriteLine(number);
        }
    }
}
示例 3:延迟执行
C#
using System;
using System.Collections.Generic;

public class DelayedExecution
{
    public static IEnumerable<int> GetNumbers()
    {
        Console.WriteLine("Start generating numbers...");
        for (int i = 1; i <= 5; i++)
        {
            yield return i;
            Console.WriteLine($"Yielded {i}");
        }
        Console.WriteLine("Finished generating numbers.");
    }
}

class Program
{
    static void Main()
    {
        IEnumerable<int> numbers = DelayedExecution.GetNumbers();
        Console.WriteLine("Before iteration");
        foreach (int number in numbers)
        {
            Console.WriteLine(number);
        }
        Console.WriteLine("After iteration");
    }
}

总结 • 简化迭代器实现:yield return 使得实现 IEnumerable 接口变得非常简单。 • 延迟执行:只有在实际迭代时才会生成数据,适用于处理大数据集或需要懒加载的场景。 • 提高代码可读性:减少了手动管理状态的复杂性,使代码更加简洁和易读。

贡献者

The avatar of contributor named as worldddddd worldddddd

文件历史

撰写

布局切换

调整 VitePress 的布局样式,以适配不同的阅读习惯和屏幕环境。

全部展开
使侧边栏和内容区域占据整个屏幕的全部宽度。
全部展开,但侧边栏宽度可调
侧边栏宽度可调,但内容区域宽度不变,调整后的侧边栏将可以占据整个屏幕的最大宽度。
全部展开,且侧边栏和内容区域宽度均可调
侧边栏宽度可调,但内容区域宽度不变,调整后的侧边栏将可以占据整个屏幕的最大宽度。
原始宽度
原始的 VitePress 默认布局宽度

页面最大宽度

调整 VitePress 布局中页面的宽度,以适配不同的阅读习惯和屏幕环境。

调整页面最大宽度
一个可调整的滑块,用于选择和自定义页面最大宽度。

内容最大宽度

调整 VitePress 布局中内容区域的宽度,以适配不同的阅读习惯和屏幕环境。

调整内容最大宽度
一个可调整的滑块,用于选择和自定义内容最大宽度。

聚光灯

支持在正文中高亮当前鼠标悬停的行和元素,以优化阅读和专注困难的用户的阅读体验。

ON开启
开启聚光灯。
OFF关闭
关闭聚光灯。

聚光灯样式

调整聚光灯的样式。

置于底部
在当前鼠标悬停的元素下方添加一个纯色背景以突出显示当前鼠标悬停的位置。
置于侧边
在当前鼠标悬停的元素旁边添加一条固定的纯色线以突出显示当前鼠标悬停的位置。