如何使[示例]扩展方法更通用/功能/高效?

时间:2010-09-07 20:36:43

标签: c# .net .net-4.0 extension-methods

我需要通过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)是首选吗?...为什么?
  • 你如何将(B)投射为IList <T[]>
  • 重构的任何好处? 可能 两种可能被链接的方法。
  • 接近声音?......还是我 错过了一些基本的东西。

总是赞赏评论,意见和苛刻的语言。

使用情况:C#.Net 4.0

3 个答案:

答案 0 :(得分:3)

B可能是更好的选择。真正的主要变化是代码的使用者可以选择在方法的末尾使用ToList()使其成为列表,而不是被迫处理List(实际上,IList,无法迭代)

这在方法链和一般用途方面具有很多优点。 ToList()很容易被枚举,但很难走向另一个方向。因此,您可以在列表上调用Select()。Split()。OrderBy()并在foreach语句中使用结果,而不必让Linq一次遍历整个事物。

重构为yield return单个值可能会给你一个性能加值,但是因为你基本上只是返回了Select给你的迭代器(它本身会产生一个项目)我不认为通过它自己屈服,你将获得很多好处。

答案 1 :(得分:2)

我更喜欢(B),因为它看起来更灵活。将(B)方法的输出转换为IList<T[]>的一种方法就像将.Select(x => x.ToArray()).ToList()链接到它一样简单,例如,

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

答案 2 :(得分:1)

在.Net 4中,您只需将返回类型更改为IEnumerable<IEnumerable<T>>即可。

在.Net 4之前,您必须首先将内部列表转换为IEnumerable,只需在返回时调用.Cast<IEnumerable<T>>()上的result