在 C# 中使用枚举器
介绍
自从程序员开始编程以来,就有一些基本的数据结构允许列出或收集特定的项目。这些项目通常被传递给其他函数进行处理或写入远程位置。这些基本数据结构(如列表)具有非常成问题的属性。假设您想将一个包含 10 个项目的列表传递给另一个函数。整数的大小为 32 位(4 字节),并将其乘以您要传输的数量。在本例中,它只有 40 字节。随着您将越来越多的项目堆积到列表中,它的大小会以线性方式增长。100 个项目意味着 400 字节;1 百万个项目会消耗 GB 的内存。并非所有系统都配备了处理这种情况的资源。yield return语句以及枚举器和可枚举器的概念可以提供帮助。
枚举器和可枚举器
有一个名为反射器的好用工具,当您使用此技术时,可以使用它来查看生成的类。
当我们谈论枚举器时,我们只是谈论枚举时使用的句柄。它指向当前元素,并可以移动到指向下一个元素。
当我们谈论可枚举时,我们只是在谈论实现一些基本协议的类或数据类型,这些协议允许枚举器遍历其项目。
简单退货声明
此函数接受一个参数,该参数指示应返回多少个偶数。
public static List<int> EvenNumbers(int max)
{
var retList = new List<int>();
int i = 0;
while (retList.Count < max)
{
retList.Add(i += 2);
}
return retList;
}
这是一个简单的例子,但如果我们检查代码,就会发现瓶颈。随着我们增加max参数,我们返回的列表变得越来越大。这是因为我们一次返回整个列表,并且在保留最大偶数的情况下执行此操作。
调用此 for 循环打印元素显示应用程序消耗了近 3GB 的内存。
foreach (int i in EvenNumbers(1000000000))
{
Console.WriteLine($"Number {i}");
}
我想你现在应该知道我在想什么。一定有更好的方法。我们希望防止我们的应用程序占用过多的内存。
输入收益率
Yield return语句会告诉我们的编译器,此函数每次调用只能返回一个元素,并且会暂停,直到请求另一个元素。当不再需要其他元素时,它就会被中断,而不会运行到结束(即耗尽)。
public static IEnumerable<int> OddNumbers(int max)
{
int i = 1;
while (i < (max * 2))
{
yield return i;
i += 2;
}
}
执行以下语句:
foreach (int i in OddNumbers(1000000000))
{
Console.WriteLine($"Number {i}");
}
注意枚举器和yield return语句的强大功能。在执行过程中,RAM使用量保持在约10MB左右,这比老式的返回整个列表方法有了很大的改进,最终结果基本相同。一个显着的区别是它返回奇数,而不是像其他函数那样返回偶数。
要么接受,要么放弃
当我们使用可枚举数据类型时,我们可以应用一个函数从我们的项目中获取特定数量的元素。
foreach (int i in OddNumbers(100).Take(10))
{
Console.WriteLine($"Number {i}");
}
这种方法仅给我们提供从可枚举数据类型排序的 100 个奇数的前 10 个元素。
整个应用程序
我想为您提供整个控制台应用程序,以便您可以进行试用。
请注意,为了转换功能,您需要在应用程序顶部使用以下两个额外的语句。
using System.Collections.Generic;
using System.Linq;
这些将为您提供“Take”函数以及将OddNumbers函数的返回类型设置为IEnumerable 的能力。
如果没有这个,您将看到一个错误,指出编译器无法找到适当的类型/函数。
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp
{
class Program
{
public static IEnumerable<int> OddNumbers(int max)
{
int i = 1;
while (i < (max * 2))
{
yield return i;
i += 2;
}
}
public static List<int> EvenNumbers(int max)
{
var retList = new List<int>();
int i = 0;
while (retList.Count < max)
{
retList.Add(i += 2);
}
return retList;
}
static void Main(string[] args)
{
//The efficient Enumerable version.
foreach (int i in OddNumbers(100).Take(10))
{
Console.WriteLine($"Number {i}");
}
// The memory hungry beast
foreach(int i in EvenNumbers(100000000))
{
Console.WriteLine($"Number: {i}");
}
Console.Read();
}
}
}
结论
我们常常误以为,通过使用功能越来越强大的计算机,我们可以忽略编写高效的代码。可枚举数据类型为您提供了创建应用程序的方法,这些应用程序可以处理大量数据,并防止它们耗尽您的所有系统资源。这种技术在整个行业中被广泛使用,它可以成为您编程工具集中非常有效的方法。
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~