我希望能够做这样的事情来设置一个 网格数据结构。
IReadOnlyList<Point> points;
IReadOnlyList<IReadOnlyList<int>> triangles;
其中三角形是点列表的索引。给出一个指数 一个三角形''''我们可以很容易地找到这些点
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属性,我只是想懒洋洋地转换值,这意味着不 事先将所有值复制到新的列表实例。
答案 0 :(得分:2)
我不相信在框架中有什么可以做到这一点,没有。这显然很容易实现,但我相信你必须这样做。完全可能有第三方库可以做到这一点,但由于IReadOnlyCollection
仅在.NET 4.5中,它比接口存在一段时间的可能性小。
我建议将其称为Select
之外的其他内容 - 我会使用ProjectView
或类似内容。当然这意味着它不适用于LINQ查询表达式,但对于阅读代码的任何人来说,只有Enumerable.Select
答案 1 :(得分:1)
这是针对问题的手动解决方案
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() );