2014-05-18 73 views
0

我是Linq的新手,使用C#。我執行以下操作時遇到了很大的驚喜:Linq選擇新對象性能

var scores = objects.Select(i => new { object = i, 
     score1 = i.algorithm1(), 
     score2 = i.algorithm2(), 
     score3 = i.algorithm3() }); 

    double avg2 = scores.Average(i => i.score2); // algorithm1() is called for every object 
    double cutoff2 = avg2 + scores.Select(i => i.score2).StdDev(); // algorithm1() is called for every object 

    double avg3 = scores.Average(i => i.score3); // algorithm1() is called for every object 
    double cutoff3 = avg3 + scores.Select(i => i.score3).StdDev(); // algorithm1() is called for every object 

    foreach(var s in scores.Where(i => i.score2 > cutoff2 | i.score3 > cutoff3).OrderBy(i => i.score1)) // algorithm1() is called for every object 
    { 
     Debug.Log(String.Format ("{0} {1} {2} {3}\n", s.object, s.score1, s.score2/avg2, s.score3/avg3)); 
    } 

我的新對象中的屬性存儲函數調用而不是值。每次嘗試訪問屬性時,都會調用原始函數。我認爲這是對時間的巨大浪費?我怎樣才能避免這種情況?

+0

您需要兌現查詢。所以在第一個select語句之後添加一個ToArray()。 – CSharpie

+0

是的,非常感謝! – user3184362

回答

1

是的,你已經發現LINQ使用延遲執行。這是LINQ的一個正常組成部分,並且非常方便,可以在不需要實際執行任何內容的情況下構建查詢,這反過來又適用於多個操作的管道,可能可以流式傳輸巨大的數據源。

有關LINQ to Objects如何在內部工作的更多詳細信息,您可能需要閱讀我的Edulinq blog series - 它基本上是將LINQ整體重新實現爲Objects,一次只能執行一次。希望到最後,你會對所期望的有更清晰的認識。

如果你想兌現查詢,你只需要調用ToListToArray打造的結果的內存副本:

var scores = objects.Select(i => new { object = i, 
    score1 = i.algorithm1(), 
    score2 = i.algorithm2(), 
    score3 = i.algorithm3() }).ToList(); 
+0

謝謝!我只是浪費了半個小時實現一個私人類,而不是使用ToList! – user3184362