2012-07-31 55 views
8

我有以下的情況下,我想一些項目添加到列表...List.AddRange與IEnumerable <T>參數不起作用?

List<T> items = new List<T>(); 
IEnumerable<T> addItems = someCollection.Where(...); 
items.AddRange(addItems); 

使用此代碼,沒有項目被添加到列表中,但如果我以後再LINQ的添加.ToList()聲明然後項目被正確添加。我想這是由於推遲執行,但我會認爲,給定的List.AddRange函數接受IEnumerable,它會列舉項目添加。

有人可以澄清爲什麼會發生這種情況嗎?

+0

這是C#,對嗎? – Antimony 2012-07-31 23:53:31

+0

對不起,是的C#(4.0) – John 2012-07-31 23:55:27

+1

你如何看到「沒有項目被添加」,因爲它應該添加項目? – 2012-08-01 00:04:01

回答

2

感謝您的答覆。我試圖簡化這個例子的代碼,但像往常一樣,細節中的魔鬼!

在.Where()語句和AddRange()調用之間,代碼是(深入)清除源(本例中的'items')列表。開發人員沒有意識到過濾器被推遲到AddRange()調用之前,他們已經清除了源列表。

很高興知道我還沒有失去的陰謀:)

4

我想這是由於推遲執行,但我會認爲,給定List.AddRange函數接受IEnumerable,它會枚舉要添加的項目。

它的確如此。 ICollection<T>(在這種情況下你不會碰到)會有短路,這會導致它使用ICollection<T>.CopyTo而不是枚舉項目,否則它將枚舉集合。

有關工作例如,嘗試:

using System; 
using System.Linq; 
using System.Collections.Generic; 

internal class Program 
{ 
    private static List<T> RunQuery<T>(IEnumerable<T> someCollection, Func<T, bool> predicate) 
    { 
     List<T> items = new List<T>(); 
     IEnumerable<T> addItems = someCollection.Where(predicate); 
     items.AddRange(addItems); 
     return items; 
    } 

    static void Main() 
    { 
     var values = Enumerable.Range(0, 1000); 

     List<int> results = RunQuery(values, i => i >= 500); 

     Console.WriteLine(results.Count); 
     Console.WriteLine("Press key to exit:"); 
     Console.ReadKey(); 
    } 
} 

,它使用了確切的代碼,並打印出500(物件的適當數量的List<T>)。

+0

OP的例子中'someCollection'可能是某種實現了'CopyTo'的空白定義的類型? – 2012-08-01 00:21:08

+0

@丹濤是的 - 可能有其他事情發生。但是,一般來說,這可以在IEnumerable 中正常工作 - 它不是「延遲執行」問題。 – 2012-08-01 00:37:42

+0

@DanTao(請注意,它需要OP有自己的「Where」方法來創建'ICollection ',並且有奇怪的實現) – 2012-08-01 00:39:05

1

它確實有效。以下是一個證明它的單元測試:

[TestFixture] 
public class AddRangeTest 
{ 
    [Test] 
    public void AddRange() 
    { 
     var list = new List<int>(); 
     var someCollection = new List<int> { 1, 2, 3 }; 
     var subItems = someCollection.Where(x => x > 1); 
     list.AddRange(subItems); 
     Assert.AreEqual(2, list.Count); 
    } 
} 

也許在您的特定場景中某些功能無法正常工作。

2

我以爲List.AddRange函數接受一個 IEnumerable它將枚舉要添加的項目。

我試過下面和AddRange(IEnumerable<T>)確實工作

List<string> someCollection = new List<string>{"A", "B", "C"}; 
List<string> items = new List<string>(); 
IEnumerable<string> addItems = someCollection.Where(x => x != ""); 
items.AddRange(addItems);