是否有一个接口指定参数(集合)可以通过整数索引?
我正在尝试使用 OrderedDictionary 作为以下扩展函数的参数(顺便说一下,如果您认为 collection.Reverse().Where(i => predicate(i)).Take(n)
会更好,让我知道!),但是我使用的通用 OrderedDictionary 实现(基于 这个版本)没有实现IList。
该集合只需要使用基于整数的索引提供对其元素的访问(OrderedDictionary 就是这样做的)。
是否有另一种方法可以指定此要求,而不会造成重载?
/// <summary>
/// Return n elements, starting from the end of collection, that satisfy predicate.
/// </summary>
/// <param name="collection"></param>
/// <param name="predicate"></param>
/// <param name="n">Max number of elements to return</param>
/// <returns></returns>
public static IEnumerable<T> LastBefore<T>(this IList<T> collection, Func<T, bool> predicate, int n) {
if (collection == null)
{
throw new ArgumentNullException("collection");
}
for (int i = collection.Count - 1; i >= 0; i--)
{
if (n == 0) break;
if (predicate(collection[i]))
{
--n;
yield return collection[i];
}
}
}
I am trying to use an OrderedDictionary as an argument for the below extension function (by the way if you think collection.Reverse().Where(i => predicate(i)).Take(n)
would be better, let me know!), but the generic OrderedDictionary implementation I use (based on this version) does not implement IList.
The collection only needs to provide access to its elements with an integer-based index (which OrderedDictionary does).
Is there another way to specify this requirement, without creating an overload?
/// <summary>
/// Return n elements, starting from the end of collection, that satisfy predicate.
/// </summary>
/// <param name="collection"></param>
/// <param name="predicate"></param>
/// <param name="n">Max number of elements to return</param>
/// <returns></returns>
public static IEnumerable<T> LastBefore<T>(this IList<T> collection, Func<T, bool> predicate, int n) {
if (collection == null)
{
throw new ArgumentNullException("collection");
}
for (int i = collection.Count - 1; i >= 0; i--)
{
if (n == 0) break;
if (predicate(collection[i]))
{
--n;
yield return collection[i];
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我建议定义一个 IReadableList 接口;如果不是因为读写索引器不算作只读索引器的实现,那么这样的东西可能是 IList 的父级(恕我直言,无论如何它都应该是)。现有的 IList 实现不会实现 IReadableList,除非进行包装,唉,但是拥有只读列表接口将使协方差的概念更加有用,因为 IReadableList会更有用。可以用作 IReadableList。
顺便说一句,我倾向于认为虽然 IList不继承自非泛型 IList,也许它应该继承。任何 IList如果非泛型实现是只读的,则可以以类型安全的方式实现 IList。即使人们从未真正从非泛型 IList 中读取任何对象,实现它也将允许一个需要 IEnumerable的例程。但被给予 IList; [当然,它实现了 IEnumerable,因此隐式实现了 IEnumerable] 来获取集合的计数,而不必枚举它。
I would suggest defining an IReadableList interface; were it not for the fact that a read-write indexer does not count as an implementation of a read-only indexer, such a thing could have been a parent of IList (IMHO, it should have been anyway). Existing IList implementations won't implement IReadableList unless wrapped, alas, but having a read-only list interface would make the concept of covariance much more useful, since an IReadableList<Cat> could be used as an IReadableList<Animal>.
Incidentally, I tend to think that while IList<T> doesn't inherit from the non-generic IList, perhaps it should. Any IList<T> could implement IList in type-safe fashion if the non-generic implementation is read-only. Even if one never actually read any objects from the non-generic IList, implementing it would make allow a routine which wants an IEnumerable<Animal> but is given an IList<Cat> [which of course implements IEnumerable<Cat>, and thus implicitly IEnumerable<Animal>] to get a Count of the collection without having to enumerate it.
根据 MSDN 关于类型约束的说法,不幸的是不是。
您最好创建 一个需要索引器,但显然你不能使用内置类来做到这一点(除非你专门为此目的定义了一个包装类)。
According to the MSDN about type constraints, unfortunately not.
Best you can do it create an interface that requires an indexer, but obviously you couldn't do that with built in classes (unless you defined a wrapper class just for that purpose).
您可以在任何
IEnumerableElementAt 。代码>.对于实现
IList
的集合,这将使用快速索引,而不是枚举直到请求的索引为止的所有元素。这提供了只读访问,并且也适用于没有内置索引支持的集合,尽管会带来性能损失。您通常会记录该方法,以表明支持索引的集合作为传入的参数更可取。如果您需要提供读写访问权限,
IList
可能是一个合理的约束;如果您需要的东西仅限于索引器,那么最好的选择是创建一个浅层包装类,它封装提供的IList
,但只向使用者提供索引器。You can use ElementAt on any
IEnumerable<T>
. For collections implementingIList<T>
, this will use fast indexing rather than enumerating all elements up to the index requested. This provides read-only access and also works with collections that don't have built-in indexing support, albeit with a performance penalty. You would typically document the method to indicate that collections supporting indexing are preferable as the argument passed in.If you need to provide read-write access,
IList<T>
is probably a reasonable constraint; if you need something limited to just the indexer, your best bet is to create a shallow wrapper class that encapsulates a providedIList<T>
, but only gives an indexer to the consumer.