无限序列意味着一个序列有无限多的元素。这似乎可以肯定,一般程序中内存是有限的,不可能生成一个无限的序列。其实,这里的无限序列指的是可以取任意多个元素。常规方法去初始化一个序列是无法实现。因此只要通过其他方式才能曲线实现。
使用IEnumerable接口,可以实现无限序列。因为IEnumerable接口继承于IEnumerator,因此实现了一个迭代器,也就是说,对于IEnumerable的实例(接口不能实例化,这里的意思指的是实现IEnumerable的类的实例)来说,可以使用迭代的方法依次遍历它的元素。而且,IEnumerable的实例中的元素,并不是在定义的时候才有,而是在真正使用它的时候才会计算。因此我们可以在定义的时候定义一个无限的序列,而真正使用的时候,肯定只是取这个无限序列中的某几个元素,这样就只需迭代这几个元素就行了。这就是延迟加载的好处。
具体实例如下,此处定义了一个无限的斐波纳契序列。
static IEnumerable<int> fib() { int pre = 0; int next = 1; while (true) { var val = pre + next; yield return val; pre = next; next = val; } }
乍一看,看到while (true),就觉得这是一个死循环,其实不然,里面有一个yield,每次迭代都会抛出值。while (true)里面的是迭代需要的循环,因为是死循环,也就是说可以迭代无数次。当然,如果你换成for循环,并且循环次数设成10次,那么只能迭代10次,这是就只是一个普通的有限序列了。
在使用这个序列的时候,可以如下:
var f = fib();//此时并未真正开始计算里面的元素。
如果要取10个元素,可以通过linq的扩展方法Take(10)取元素,但是要知道,Take(10)这个函数也并未正真的去取10个数,只有在真正用到的时候,才回去计算这些元素。
var list=f.Take(10);
下面的代码要遍历这个序列,此时才会正真去计算里面的元素值。
foreach (var i in list ) { Console.WriteLine(i); }
或者在Take(10)之后直接调用ToList,也能使得序列马上计算其中的元素。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。