c#迭代器的双重使用出乎意料
本文关键字:出乎意料 迭代器 | 更新日期: 2023-09-27 18:10:25
这是我第一次用c#编码-我有C/Python/Javascript/Haskell的背景。
为什么下面的程序可以工作?我希望这在Haskell中工作,因为列表是不可变的,但我正在努力解决如何使用相同的迭代器nums
两次而没有错误。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
var nums = new List<int?>() { 0, 0, 2, 3, 3, 3, 4 };
var lastNums = new List<int?>() { null } .Concat(nums);
var changesAndNulls = lastNums.Zip(nums,
(last, curr) => (last == null || last != curr) ? curr : null
);
var changes = from changeOrNull in changesAndNulls where changeOrNull != null select changeOrNull;
foreach (var change in changes) {
Console.WriteLine("change: " + change);
}
}
}
}
在你的代码中nums
不是IEnumerator<T>
(迭代器),它是IEnumarable<T>
和IEnumarable <T>
有GetEnumerator()
方法,可以作为多次调用根据需要:
IEnumerable<int?> nums = new List<int?>() { 0, 0, 2, 3, 3, 3, 4 };
// Linq gets enumerator to do Concat
using (var iterator1 = nums.GetEnumerator()) {
while (iterator1.MoveNext()) {
...
}
}
...
// Linq gets (fresh!) enumerator to do Zip
using (var iterator2 = nums.GetEnumerator()) {
while (iterator2.MoveNext()) {
...
}
}
所以IEnumerable<T>
是一个工厂生产IEnumerator<T>
实例(这是一个IEnumerator<T>
不能被重用)
List<int?>
实现接口IEnumerable<int?>
。这意味着它有一个叫做GetEnumerator()
的方法。此方法返回一个新的Enumerator<int?>
对象,用于遍历所有项。
当你在foreach循环中使用GetEnumerator()
时,或者当你调用Concat()
等许多扩展方法之一时,你正在调用CC_14(在后台)。
我建议你上c#的教程。它是一种与Haskell非常不同的语言,它有一些非常独特的特性。首先:http://en.wikipedia.org/wiki/C_Sharp_syntax