2015-05-27 17 views
1

List<T>()System.Collections.Generic缺省容量是0提供大小參數來列出<T>()

說我有一個功能

private IEnumerable<SomeType> DoStuff(IEnumerable<OtherType> e) 
{ 
    var list = new List<SomeType>(); 
    foreach (var elem in e) 
    { 
     list.Add(new SomeType 
     { 
      SomeProperty = elem.OtherProperty 
     }); 
    } 
    return list; 
} 

和予設定的list大小運行循環像這樣前:

private IEnumerable<SomeType> DoStuff(IEnumerable<OtherType> e) 
{ 
    var list = new List<SomeType>(e.Count()); 
    foreach (var elem in e) 
    { 
     list.Add(new SomeType 
     { 
      SomeProperty = elem.OtherProperty 
     }); 
    } 
    return list; 
} 

它是否在運行時間有所不同或是沒有理由這樣做,因爲大小e是'動態'?

+0

試試看看。爲預期內容提供足夠大的尺寸將防止發生在引擎蓋下的重新分配。 –

+1

但是,如果你只是在一個列表上進行轉換,爲什麼不使用LINQ的Select()? –

回答

5

這取決於IEnumerable<OtherType> e類型...

e.Count() 

可以列舉e只是指望它......如果e兌數據庫查詢時,它會在被執行兩次,一次e.Count()和一次爲foreach ...慢!

如果eList<>OtherType[]或其他類型的實現ICollection<>那麼Count()使用Count屬性,因此它不枚舉IEnumerable<>

注意,對於你可以這個簡單的例子:

return e.Select(x => new SomeType { SomeProperty = x.OtherProperty }) 
     .ToList(); 

現在...作爲@Jonathan注意到,您在返回IEnumerable<>,所以你可以:

return e.Select(x => new SomeType { SomeProperty = x.OtherProperty }); 

和生活幸福。 ..或者你可以

private IEnumerable<SomeType> DoStuff(IEnumerable<OtherType> e) 
{ 
    foreach (var elem in e) 
    { 
     yield return new SomeType 
     { 
      SomeProperty = elem.OtherProperty 
     }; 
    } 
} 

(這將是幾乎等同於做Select,但如果你有一個複雜的表達式轉換的元素,也許使用Select變得繁瑣)

或者,如果你真的想創建一個List<>和底膠,如果它是可能的:

ICollection<T> c = e as ICollection<T>; 
int count = c != null ? c.Count : 0; 

var list = new List<SomeType>(count); 

與往常一樣,請記住,你不應列舉的IEnumerable<>不止一次,除非你是真的確保

  1. 這實在是一種變相的List<>或其他集合,從而使數據已經存在,並且沒有問題枚舉它多次

  • 你知道每次IEnumerable<>枚舉將從頭開始重建,但成本可以忽略不計。
  • +0

    ToList爲什麼? –

    +0

    「選擇」是1到1列表的路線。 – Franck

    +0

    @JonathonReinhart因爲他正在構建一個'List <>'可以在緩存IEnumerable <>'時有一些時間差別:-)是的......如果你想要的話,你可以去掉ToList <>() – xanatos

    3

    不要這樣做。這樣,你可以列舉兩次序列e:一次在foreach之內,一次通過Count()

    將容量賦予List<T>構造函數的想法是防止不必要的數組分配。該列表動態增長,這意味着它將分配一個新的數組,這個數組的長度是必要時的兩倍。如果它知道所需容量,List<T>可以從一開始就分配正確大小的數組。

    有關的一般建議是否會影響運行時間度量值,請不要假設爲。你可以在這裏節省數組的分配,但是你可能會比較慢,因爲你不止一次遍歷序列。

    +0

    取決於IEnumerable的類型,但它是一個好點 – Jehof

    +0

    *可能*。 .Count()可以專門用於像數組這樣的事物,並且可以在O(1)中運行,因爲大小是已知的。 –

    +0

    是的,你是對的。但由於'DoStuff'接受任何序列,所以不應該迭代多次。不過,您可以嘗試進行演員製作,並根據此決定作出決定。 –