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

IEnumerable<T>.ConvertAll&DDD

  •  2
  • n8wrl  · 技术社区  · 16 年前

    我对IEumerable接口上的扩展方法有一个有趣的需求——与List.ConvertAll一样。这一点以前已经讨论过了 here 我找到了一个解决办法 here . 我不喜欢这个解决方案的地方是他构建了一个列表来保存转换后的对象,然后返回它。我怀疑LINQ写文章时不在,所以我的实现是:

    public static class IEnumerableExtension
    {
        public static IEnumerable<TOutput> ConvertAll<T, TOutput>(this IEnumerable<T> collection, Func<T, TOutput> converter)
        {
            if (null == converter)
                throw new ArgumentNullException("converter");
    
            return from item in collection
                   select converter(item);
        }
    }
    

    我更喜欢的是,我可以“即时”转换,而不必加载所有TOutput的列表。注意,我还将委托的类型从Converter更改为Func。编译是一样的,但我认为这让我的意图更清楚了——我不是说这只是类型转换。

    这就引出了我的问题:在我的存储库层中,我有很多查询返回实体的ID-ID列表。我曾经有几个类以各种方式将这些ID“转换”为实体。通过这种扩展方法,我可以将所有这些归结为如下代码:

    IEnumerable<Part> GetBlueParts()
    {
        IEnumerable<int> keys = GetBluePartKeys();
        return keys.ConvertAll<Part>(PartRepository.Find);
    }
    

    其中“转换器”实际上是存储库的按ID查找方法。在我的例子中,“转换器”可能发挥了相当大的作用。有人认为这种方法有什么问题吗?

    2 回复  |  直到 9 年前
        1
  •  10
  •   Reed Copsey    16 年前

    我认为这种方法的主要问题是完全没有必要。

    你的 ConvertAll Enumerable.Select<TSource,TResult>(IEnumerable<TSource>, Func<TSource,TResult>) ,这是一个标准LINQ运算符。没有理由为框架中已经存在的东西编写扩展方法。

    您只需执行以下操作:

    IEnumerable<Part> GetBlueParts() 
    { 
        IEnumerable<int> keys = GetBluePartKeys(); 
        return keys.Select<int,Part>(PartRepository.Find); 
    } 
    

    <int,Part> 以及编译,除非 PartRepository.Find

    IEnumerable<Part> GetBlueParts() 
    { 
        IEnumerable<int> keys = GetBluePartKeys(); 
        return keys.Select(i => PartRepository.Find<Part>(i)); // I'm assuming that fits your "Find" syntax...
    } 
    
        2
  •  1
  •   Justin Niessner    16 年前

    为什么不利用 yield 关键字(并且仅在需要时转换每个项目)?

    public static class IEnumerableExtension
    {
        public static IEnumerable<TOutput> ConvertAll<T, TOutput>
            (this IEnumerable<T> collection, Func<T, TOutput> converter)
        {
            if(null == converter)
                throw new ArgumentNullException("converter");
    
            foreach(T item in collection)
                yield return converter(item);
        }
    }