2010-09-07 94 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();