Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 重复使用C迭代器会意外地工作_C#_Linq_Iterator - Fatal编程技术网

C# 重复使用C迭代器会意外地工作

C# 重复使用C迭代器会意外地工作,c#,linq,iterator,C#,Linq,Iterator,这是我第一次尝试用C编写代码——我有C/Python/Javascript/Haskell的背景 为什么下面的程序有效?我希望这在Haskell中能起作用,因为列表是不可变的,但我正在努力解决如何两次使用相同的迭代器nums而不出错的问题 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace HelloWorld { class Program

这是我第一次尝试用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);
            }
        }
    }
}
列表实现接口IEnumerable。这意味着它有一个名为GetEnumerator的方法。 此方法返回一个用于迭代所有项的新枚举器对象

当您在foreach循环中使用GetEnumerator时,或者当您调用许多扩展方法(如Concat)中的一个时,您正在后台调用GetEnumerator,而Concat本身调用GetEnumerator

我建议你学习C语言教程。它与Haskell语言非常不同,并且有一些非常独特的特性。 仅供初学者参考:

在您的代码中,nums不是IEnumerator迭代器,而是IEnumarable,IEnumarable具有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是一个工厂生产的IEnumerator实例,它是一个不能重复使用的IEnumerator

哪行代码以意外的方式工作?重复使用在哪里?nums不是IEnumerator,它是IEnumerable,它有GetEnumerator方法来调用任意times@AdamHouldsworthnums和lastNums都以迭代器的形式访问nums,并在Zip中并行使用。@chrisdew nums不是迭代器,它是一个可迭代的集合,只是被迭代两次,这是允许的,因为遍历它的每个迭代器都是自己独立的状态机。它与问题无关,也没有人使用过此功能,但IEnumerator可以通过调用Reset来重用。尽管它在这里不起作用,因为枚举数的两种用法是并行的。