2010-09-07 91 views
2

我需要通過stride y返回一個List來將double []拆分爲x個元素的組。很基本...一個循環和/或一些linq和你所有的設置。然而,我沒有花太多時間在延伸方法上,這看起來是一些練習的好選擇。該天真的版本返回什麼,我希望在我的當前應用程序....如何使[示例]擴展方法更通用/功能/高效?

(A) 
public static IList<T[]> Split<T>(this IEnumerable<T> source, int every, int take) 
{ 
    /*... throw E if X is insane ...*/ 
    var result = source 
       .Where ((t, i) => i % every == 0) 
       .Select((t, i) => source.Skip(i * every).Take(take).ToArray()) 
       .ToList(); 
    return result; 
} 

...返回類型是那種普通的... 取決於您的通用定義。

我想...

(B)  
public static IEnumerable<IEnumerable<T>> Split<T> 
        (this IEnumerable<T> source,int every, int take){/*...*/} 

...是一個更好的解決方案......也許。

問題(S):

  • 是(B)首選...爲什麼?
  • 你會如何投(乙)IList <T[]>
  • 重構有什麼好處? 可能 兩種可能被鏈接的方法等。
  • 該方法的聲音?...或有我 錯過了一些基本的東西。

評論,意見和苛刻的語言總是讚賞。

佔用率背景:C#.NET 4.0

回答

3

乙可能是更好的選擇。真正的主要變化是代碼的使用者可以選擇使用方法末尾的ToList()作爲列表,而不是被迫處理List(實際上是一個不能迭代的IList) 。

這在方法鏈和一般使用方面有很多優點。 ToList()很容易枚舉,但很難以其他方式。因此,您可以在列表中調用Select().Split()。OrderBy()方法,並在foreach語句中使用結果,而不必讓Linq一次遍歷整個事件。

重構爲yield return單個值可能會給你一個性能獎勵,但由於你基本上只是返回Select給你的迭代器(它一次會產生一個項目),我不認爲你會通過它自己屈服可以獲得很多好處。

1

在.NET 4中,你可以改變返回類型IEnumerable<IEnumerable<T>>,它會工作。

在.Net 4之前,您必須首先將內部列表投射到IEnumerable,在返回之前您只需在result上撥打.Cast<IEnumerable<T>>()即可。

+1

爲什麼要調用'Cast'而不是簡單地移除'ToArray'和'ToList'調用? – jball 2010-09-07 21:00:00

+0

@jball:如果您希望查詢熱切執行,則存在合法的區別。 – Ani 2010-09-07 21:07:16

+0

@Ani,它似乎違背了LINQ和擴展方法的期望,使得一個急切執行的擴展方法。 – jball 2010-09-07 21:10:11

2

我更喜歡(B),因爲它看起來更加靈活。在(B)方法的輸出轉換成一IList<T[]>的一種方式是作爲鏈.Select(x => x.ToArray()).ToList()它,例如,作爲簡單,

var foo = 
    bar.Split(someEvery, someTake).Select(x => x.ToArray()).ToList();