代码之家  ›  专栏  ›  技术社区  ›  Rusty

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

  •  2
  • Rusty  · 技术社区  · 14 年前

    我需要一个双[]分割成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 回复  |  直到 14 年前
        1
  •  3
  •   KeithS    14 年前

    B可能是更好的选择。实际上,主要的变化是代码的使用者可以选择在方法的末尾使用to list()将其设置为一个列表,而不是强制处理一个列表(实际上是一个ilist,它不能被迭代)。

    这在方法链接和一般应用方面有很多优点。很容易列出一个可枚举的,但很难找到另一种方法。因此,您可以在列表中调用select().split().orderby(),并在foreach语句中使用结果,而不必让linq一次遍历整个过程。

    重构到 yield return 单值可能会给您带来性能奖励,但由于您基本上只是返回select给您的迭代器(它一次只产生一个项目本身),所以我认为您自己通过它获得的收益不大。

        2
  •  2
  •   jball    14 年前

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

    var foo = 
        bar.Split(someEvery, someTake).Select(x => x.ToArray()).ToList();
    
        3
  •  1
  •   bdukes Jon Skeet    14 年前

    在.NET 4中,只需将返回类型更改为 IEnumerable<IEnumerable<T>> 它会起作用的。

    在.NET 4之前,必须将内部列表强制转换为 IEnumerable 首先,只要打电话 .Cast<IEnumerable<T>>() 对你 result 返回前。