【问题标题】:Lazily Transforming IReadOnlyList in C#在 C# 中懒惰地转换 IReadOnlyList
【发布时间】:2013-03-13 15:49:14
【问题描述】:

我希望能够做这样的事情来建立一个 网状数据结构。

IReadOnlyList<Point> points;
IReadOnlyList<IReadOnlyList<int>> triangles;

其中三角形是点列表的索引。给定一个索引 我们可以很容易地找到三角形''ti''的点

IEnumerable<Point> points = triangles[ti].Select(pi=>points[pi])

但是我希望能够定义一个方便的结构

IReadOnlyList<IReadOnlyList<Point>> trianglesAsPoints;

这样我就可以了

IEnumerable<Point> points = triangles[ti]

这样做的明显方法是创建一个类似于选择器的 linq

IReadOnlyList<T> Select( this IReadOnlyList<U> This
                             , Func<U,T> selector)

它返回一个实例,其类覆盖以下方法和 调用选择器

public interface IReadOnlyList<out T> : IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable
{
    // Summary:
    //     Gets the element at the specified index in the read-only list.
    //
    // Parameters:
    //   index:
    //     The zero-based index of the element to get.
    //
    // Returns:
    //     The element at the specified index in the read-only list.
    T this[int index] { get; }
}

这种模式的标准库或 nuget 中是否存在这样的工厂? 注意我不希望 IEnumerable 结果因为我会失去索引能力 和 Count 属性,我只想懒惰地转换值,这意味着 not 将所有值复制到前面的新列表实例中。

【问题讨论】:

    标签: c# list


    【解决方案1】:

    我不相信框架中有任何东西可以做到这一点,不。自己实现显然相当容易,但我相信你必须这样做。完全有可能有 3rd 方库来执行此操作,但由于 IReadOnlyCollection 仅在 .NET 4.5 中,因此与接口存在一段时间相比,这种可能性较小。

    我建议将其命名为 Select 以外的其他名称 - 我会使用 ProjectView 或类似名称。当然,这意味着它不适用于 LINQ 查询表达式,但任何阅读代码的人都会更清楚它只是Enumerable.Select

    【讨论】:

      【解决方案2】:

      这是一个手工解决问题的方法

      public static class CollectionMixins
      {
          private class ReadOnlyListProjection<U,T> : IReadOnlyList<T>
          {
      
              public Func<U,T> Selector { get; private set; }
              public IList<U> List { get; private set; }
      
              public ReadOnlyListProjection(IList<U> list, Func<U, T> selector)
              {
                  List = list;
                  Selector = selector;
              }
      
              public T this[int index]
              {
                  get { return Selector(List[index]);  }
              }
      
              public int Count
              {
                  get { return List.Count; }
              }
      
              public IEnumerator<T> GetEnumerator()
              {
                  return List.Select(Selector).GetEnumerator();
              }
      
              System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
              {
                  return List.Select(Selector).GetEnumerator();
              }
          }
      
          public static IReadOnlyList<T> ProjectReadOnly<U, T>(this IList<U> This, Func<U, T> fn)
          {
              return new ReadOnlyListProjection<U, T>(This, fn);
          }
      }
      

      所以我现在可以做

      IList<int> foo = new List<int>{0,1,2};
      IReadOnlyList<string> bar = foo.ProjectReadOnly( x=>x.ToString() );
      

      【讨论】:

        猜你喜欢
        • 2014-05-31
        • 1970-01-01
        • 2011-12-31
        • 1970-01-01
        • 2023-03-14
        • 1970-01-01
        • 2010-09-26
        • 2015-12-19
        • 1970-01-01
        相关资源
        最近更新 更多