首页 > 编程语言 > 《c#高级编程》第2章C#2.0中的更改(三)——迭代器

《c#高级编程》第2章C#2.0中的更改(三)——迭代器

时间:2023-04-24 22:35:48浏览次数:32  
标签:return 迭代 item c# GetEnumerator C# int 2.0 public

一、概念

C#迭代器(Iterator)是一种特殊类型的方法,它使得在使用循环遍历数据集合时更加简单和有效。使用迭代器可以通过简单地定义迭代器方法来自动实现枚举器模式。

当您需要访问一个数据集合中的每个元素时,可以使用迭代器来遍历该集合。C#中的迭代器通过yield关键字实现。yield语句用于指示方法返回一个序列,并返回一系列值。这些值会被逐个返回到调用方,并且方法的当前状态会保留下来,以便下次调用时继续执行。

以下是一个使用迭代器的简单示例,其中展示了如何使用它来遍历整数数组:

```csharp
static IEnumerable<int> GetNumbers()
{
int[] numbers = { 1, 2, 3, 4, 5 };
foreach (int number in numbers)
{
yield return number;
}
}
```

在这个示例中,GetNumbers()方法返回一个IEnumerable<int>类型的迭代器。在foreach循环中,使用yield return语句依次返回数组中的每个数字。

使用迭代器有以下几个好处:

1. 简化代码结构:使用迭代器使得代码结构更加清晰、简洁。

2. 节省内存:由于迭代器只是逐个返回序列中的元素,所以可以大大减少内存的使用。

3. 延迟计算:当使用yield return语句时,元素是按需生成的,这意味着在需要时才会计算。这可以提高性能,并允许处理非常大的数据集合。

4. 支持Linq查询:由于迭代器实现了IEnumerable和IEnumerator接口,因此它们可以与Linq查询一起使用。

总之,C#迭代器是一种非常有用的工具,它使得遍历和操作数据集合变得更加简单、高效和灵活。通过使用yield关键字,可以轻松地定义自己的迭代器方法,并利用其强大的功能来提高代码质量和性能。

二、使用场景

以下是使用C#迭代器的经典场景和演示代码:

  1. 遍历集合数据

使用 C# 迭代器可以更方便地遍历一个集合中的所有元素,而不必事先知道集合的大小。

public class MyList<T> : IEnumerable<T>
{
    private List<T> _list;

    public MyList()
    {
        _list = new List<T>();
    }

    public void Add(T item)
    {
        _list.Add(item);
    }

    public IEnumerator<T> GetEnumerator()
    {
        for (int i = 0; i < _list.Count; i++)
        {
            yield return _list[i];
        }
    }

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

// 使用 MyList 遍历元素
var list = new MyList<int>();
list.Add(1);
list.Add(2);
list.Add(3);

foreach (var item in list)
{
    Console.WriteLine(item);
}

输出结果:
1
2
3
  1. 实现延迟加载

使用 C# 迭代器可以实现延迟加载,也就是说只有在需要访问某个元素时才会去加载它,从而提高程序的性能和效率。

public class LazyDataLoader<T> : IEnumerable<T>
{
    private Func<IEnumerable<T>> _dataLoader;

    public LazyDataLoader(Func<IEnumerable<T>> dataLoader)
    {
        _dataLoader = dataLoader;
    }

    public IEnumerator<T> GetEnumerator()
    {
        foreach (var item in _dataLoader())
        {
            yield return item;
        }
    }

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

// 使用 LazyDataLoader 延迟加载数据
var dataLoader = new LazyDataLoader<int>(() => Enumerable.Range(1, 100000));
    
foreach (var item in dataLoader)
{
    Console.WriteLine(item);
}

输出结果:
1
2
...
99999
100000
  1. 处理大型数据集

如果数据集非常大,无法一次性全部加载到内存中,使用 C# 迭代器可以分批次地读取数据,从而降低内存消耗。

public class BigDataLoader<T> : IEnumerable<T>
{
    private Func<IEnumerable<T>> _dataLoader;
    private int _batchSize;

    public BigDataLoader(Func<IEnumerable<T>> dataLoader, int batchSize)
    {
        _dataLoader = dataLoader;
        _batchSize = batchSize;
    }

    public IEnumerator<T> GetEnumerator()
    {
        var buffer = new T[_batchSize];
        var count = 0;

        foreach (var item in _dataLoader())
        {
            buffer[count++] = item;

            if (count == _batchSize)
            {
                for (int i = 0; i < count; i++)
                {
                    yield return buffer[i];
                }

                count = 0;
            }
        }

        for (int i = 0; i < count; i++)
        {
            yield return buffer[i];
        }
    }

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

// 使用 BigDataLoader 分批次读取数据
var bigDataLoader = new BigDataLoader<int>(() => Enumerable.Range(1, 100000), 1000);

foreach (var item in bigDataLoader)
{
    Console.WriteLine(item);
}
输出结果:
1
2
...
99999
100000
  1. 实现自定义的遍历逻辑

有时候我们需要按照特定的顺序或方式遍历集合数据,使用 C# 迭代器可以方便地实现自定义的遍历逻辑。

public class EvenNumberGenerator : IEnumerable<int>
{
    private int _start;
    private int _end;

    public EvenNumberGenerator(int start, int end)
    {
        _start = start % 2 == 0 ? start : start + 1;
        _end = end % 2 == 0 ? end : end - 1;
    }

    public IEnumerator<int> GetEnumerator()
    {
        for (int i = _start; i <= _end; i += 2)
        {
            yield return i;
        }
    }

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

// 使用 EvenNumberGenerator 遍历偶数
var evenNumbers = new EvenNumberGenerator(10, 20);

foreach (var item in evenNumbers)
{
    Console.WriteLine(item);
}
输出结果:
10
12
14
16
18
20
  1. 简化代码结构

使用 C# 迭代器可以简化代码结构,使得代码更加易读易懂,从而提高代码的可维护性和可读性。

public class FibonacciSequence : IEnumerable<int>
{
    private int _count;

    public FibonacciSequence(int count)
    {
        _count = count;
    }

    public IEnumerator<int> GetEnumerator()
    {
        int a = 0;
        int b = 1;

        for (int i = 0; i < _count; i++)
        {
            yield return a;

            int temp = a;
            a = b;
            b = temp + b;
        }
    }

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

// 使用 FibonacciSequence 生成斐波那契数列
var fibonacci = new FibonacciSequence(10);

foreach (var item in fibonacci)
{
    Console.WriteLine(item);
}

输出结果:
0
1
1
2
3
5
8
13
21
34

 

标签:return,迭代,item,c#,GetEnumerator,C#,int,2.0,public
From: https://www.cnblogs.com/DinAction/p/17351189.html

相关文章

  • 电力系统潮流计算matlab仿真,计算结果自动保存到excel文件中
    1.算法仿真效果matlab2022a仿真结果如下:2.算法涉及理论知识概要在电力工程中,“潮流”还特指电网各处电压(包括幅值与相角)、有功功率、无功功率等的分布。潮流的分布是运行调度单位和维修部门所必须知道的事项。而潮流计算,是指给定电网中一些参数、已知值和未知值中假设的初始......
  • 关于 SAP Commerce Cloud 构建的 Node.js 版本号问题
    假设SAPccv2某个时间点A上cloudportal支持Node.js14,16和18三个版本,然后到了时间点B,就只支持16和18了。那么在时间点A基于14构建和部署的镜像仍然能够在时间点B工作,只是在时间点B之后,不能再继续触发版本14的构建和部署了。SAPCommerceCloud不......
  • [C#]中String、String[]、List<string>相互转换及string成员substring、split简单使用
    一、相互转换1.String>String[]Strings="a,b,c,d,e";String[]sArray=s.Split(',');2.String[]>Stringstring[]sArray={"a","b","c","d","e"};strings=String.Join(",......
  • tracecompass 基于trace+log 分析系统性能问题的gui 工具
    tracecompass是eclipse社区贡献的,支持对于trace以及log进行方便的分析,可以用来快速分析系统性能问题支持多种trace格式,包含了linux,标准jaeger,linpacp,lltng,gdbtrace是一个很不错的工具,同时官方也提供了比较完备的资料可以参考说明tracecompass是一个值得使用的工具,值得......
  • vue项目中引入echarts中国地图
     最近项目中根据项目需求,展示中国地图一、下载echarts插件(我这里使用的是 4.9.0 版本)[email protected]二、在需要使用的页面引入echarts(这里是单独封装了地图组件) components/map.vue<template><divclass="map-view"><divid="main"></d......
  • ChatGPT免费第一版本
        最近利用空余时间做了一个供大家免费体验的chatgpt国内可直接访问的版本    输入12335gpt.com可直接 贴上GPT给我回复的内容,......
  • C# WakeOnLan 唤醒局域网内电脑
    首先需要开启被唤醒电脑的WOL功能进入BIOS,寻找有关WOL相关项,我的电脑BIOS里面叫做networkstack打开网卡界面,选中网卡右键打开属性 然后点击配置 选择高级,启用唤醒幻数据包 选择电源管理,勾选以下2个选项 C#唤醒局域网内电脑代码namespaceWakeOnLan{in......
  • 电力系统潮流计算matlab仿真,计算结果自动保存到excel文件中
    1.算法仿真效果matlab2022a仿真结果如下:  2.算法涉及理论知识概要       在电力工程中,“潮流”还特指电网各处电压(包括幅值与相角)、有功功率、无功功率等的分布。潮流的分布是运行调度单位和维修部门所必须知道的事项。       而潮流计算,是指给定电网中一......
  • Navicat连接Oracle报错:ORA-28547...
    使用Navicat连接正常的oracle数据库时,提示 可能是因为Navicat本地的OCI版本与Oracle数据库版本不符造成的,可以下载对应的OCI版本在Navicat中使用。1.下载OCI搜索oracleinstantclient找到相关下载地址OracleInstantClientDownloads根据实际oracle数据库版本选择对应in......
  • 【ⓈSpring & Spring MVC】Spring核心接口InitializingBean与SmartInitializingSingle
    SmartInitializingSingletonSmartInitializingSingleton中只有一个接口afterSingletonsInstantiated(),其作用是在spring容器管理的所有单例对象(非懒加载对象)初始化完成之后调用的回调接口。InitializingBeanInitializingBean接口为bean提供了初始化方法的方式,它只包括afterProp......