我想要一个协变集合,其项目可以通过索引检索。 IEnumerable 是我所知道的唯一协变的 .net 集合,但它不支持此索引。
具体来说,我想这样做:
List<Dog> dogs = new List<Dog>();
IEnumerable<Animal> animals = dogs;
IList<Animal> animalList = dogs; // This line does not compile
现在,我知道为什么这是个问题了。 list 工具ICollection
有一个 Add 方法。通过转换到 IList
的动物,它将允许后续代码添加“真实”中不允许的任何类型的动物List<Dog>
收藏。
那么有人知道支持同时协变的索引查找的集合吗?我不想创建自己的。
最佳答案
更新:从 .NET 4.5 开始有 IReadOnlyList<out T>
和 IReadOnlyCollection<out T>
它们都是协变的;后者基本上是 IEnumerable<out T>
加上 Count
;前者添加 T this[int index] {get;}
.还应该注意的是 IEnumerable<out T>
从 .NET 4.0 开始是协变的。
两者都是 List<T>
和 ReadOnlyCollection<T>
(通过 List<T>.AsReadOnly()
)实现这两个。
如果它只有 get
,它只能是协变的索引器,即
public T this[int index] { get; }
但所有主要收藏都有{get;set;}
,这让人很尴尬。我不知道那里有什么足够的,但你可以包装它,即写一个扩展方法:
var covariant = list.AsCovariant();
它是 IList<T>
的包装器只暴露 IEnumerable<T>
和 get
索引器...?应该只需要几分钟的工作...
public static class Covariance
{
public static IIndexedEnumerable<T> AsCovariant<T>(this IList<T> tail)
{
return new CovariantList<T>(tail);
}
private class CovariantList<T> : IIndexedEnumerable<T>
{
private readonly IList<T> tail;
public CovariantList(IList<T> tail)
{
this.tail = tail;
}
public T this[int index] { get { return tail[index]; } }
public IEnumerator<T> GetEnumerator() { return tail.GetEnumerator();}
IEnumerator IEnumerable.GetEnumerator() { return tail.GetEnumerator(); }
public int Count { get { return tail.Count; } }
}
}
public interface IIndexedEnumerable<out T> : IEnumerable<T>
{
T this[int index] { get; }
int Count { get; }
}
关于c# - 协方差和 IList,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38755591/