小记扩展方法的延迟执行

描述这样一个场景:

一个程序,执行的时候没有成功连接到数据存储引擎,当源源不断的新增数据要添加到数据存储里的时候就不能正常添加,此时需要一个临时存储方式。 假设先用一个缓存保存,然后当缓存数据量达到一定数量时,就取出这些数据开辟单独线程用其他保存方式进行保存。

 然后看一段模拟代码:

IList<int> cache = new List<int>();
            
int i = 0;
            
while(i<1000)
            {
                cache.Add(i);
                i
++;
            }
            var temp 
= cache.Take(100); 
            cache.Clear();
            
foreach (var p in temp)
            {
                Console.WriteLine(p);
            }

这段代码用了 Take<T>() 这个扩展方法, 这里要说的是,要做好从cache里取出前面的N条数据的方法有很多,

但是如果你这样使用了Take<T>() 方法你就会发现,你的temp里面什么都没有,

原因在与Take<T>() 是延迟执行的,而在Take<T>() 方法的下句已经执行了cache.clear() 清空了源数据,所有在foreach时候真正取数据的时候cache已经为空了,

Take<T>()自然就取不到数据了;

以下摘抄一点MSDN内容供大家参考;


此方法通过使用延迟执行实现。即时返回值为一个对象,该对象存储执行操作所需的所有信息。只有通过直接调用对象的 GetEnumerator 方法或使用 Visual C# 中的 foreach(或 Visual Basic 中的 For Each)来枚举该对象时,才执行此方法表示的查询。 

那么,在上面这段示例代码中,如何修改使其得到正确结果呢,请看下面:

 IList<int> cache = new List<int>();
            
int i = 0;
            
while (i < 1000)
            {
                cache.Add(i);
                i++;
            }
            var temp = cache.Take(100).ToList();
            cache.Clear();
            
foreach (var p in temp)
            {
                Console.WriteLine(p);
            }

很简单,将Take<T>() 的执行结果 ToXXX 一下就可以了,这里有ToList()  ToArray() 等方法都是同样一个道理。

通过这个小例可以发现在使用Linq带来的便捷的同时,对于扩展方法也需小心使用。

原文地址:https://www.cnblogs.com/cxwx/p/1867520.html