2016-01-24 100 views
0

为什么每次循环IEnumerable而不是在初始Select期间,都会创建实例?为什么选择新实例只能在枚举上构造?

this.bars = this.values.Select(x => new Bar(x)); 

我期望通过价值循环,选择一个新的酒吧,然后有,但已经测试了它,它在那一刻产生没有任何实例,而不是通过它创建新实例每次时间循环。

private IEnumerable<Bar> bars; 

酒吧现场被声明为IEnuermable,所以我不明白它如何能够保持任何形式的功能或关闭。

  • 这是预期的行为,如果是这样,为什么?
  • 我如何用Linq做这件事,但是在那里和那里创建一组新的实例?

控制台测试应用程序的完整的源:

namespace LINQ_Test 
{ 
    using System.Collections.Generic; 
    using System.Diagnostics; 
    using System.Linq; 

    public class Bar 
    { 
     private int value; 

     public Bar(int value) 
     { 
      this.value = value; 
      Debug.WriteLine("CTOR: " + value); 
     } 
    } 

    public class Foo 
    { 
     private IEnumerable<Bar> bars; 
     private IEnumerable<int> values = new int[] { 0, 1234, -1 }; 

     public void LoopValues() 
     { 
      Debug.WriteLine("Looping through bars 3 times:"); 
      for (int loop = 0; loop < 3; loop++) 
      { 
       foreach (Bar bar in this.bars) 
       { 
       } 
       Debug.WriteLine(" (next loop)"); 
      } 
      Debug.WriteLine("-\n"); 
     } 

     public void SetupValues() 
     { 
      Debug.WriteLine("Settings up bars:"); 
      this.bars = this.values.Select(x => new Bar(x)); 
      Debug.WriteLine("-\n"); 
     } 
    } 

    internal class Program 
    { 
     private static void Main(string[] args) 
     { 
      Foo foo = new Foo(); 
      foo.SetupValues(); 
      foo.LoopValues(); 
     } 
    } 
} 

APP输出:

Settings up bars: 
- 

Looping through bars 3 times: 
CTOR: 0 
CTOR: 1234 
CTOR: -1 
    (next loop) 
CTOR: 0 
CTOR: 1234 
CTOR: -1 
    (next loop) 
CTOR: 0 
CTOR: 1234 
CTOR: -1 
    (next loop) 
- 
+3

是的,这是预期的行为。你可以使用'this.values.Select(x => new Bar(x))枚举一次。ToList();''我认为在这种情况下,ReSharper甚至会告诉你'IEnumerable可能多枚举'。 –

+1

这是预期的行为,谷歌Linq懒惰评估。 –

+0

这必须是一个常见问题... –

回答

2

是的,这是预期的行为,并在IEnumerable#Select documentation记录。从该链接开始:

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

如果您希望立即完成,可以立即列举它,也许用ToList

+1

啊,就这样!我明白现在发生了什么,谢谢你。 – Octopoid