协方差和 IList [英] Covariance and IList

查看:27
本文介绍了协方差和 IList的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一个可以通过索引检索项目的协变集合.IEnumerable 是我所知道的唯一一个协变的 .net 集合,但它没有这种索引支持.

具体来说,我想这样做:

List狗 = 新列表<狗>();IEnumerable<动物>动物 = 狗;IList<动物>动物列表 = 狗;//这行不编译

现在,我知道这是一个问题的原因了.List 实现了具有 Add 方法的 ICollection.通过向上转换到 Animals 的 IList,它将允许后续代码添加任何类型的动物,而这在真实"List 集合中是不允许的.>

那么有人知道支持索引查找的集合也是协变的吗?我不想创建自己的.

解决方案

更新:从 .NET 4.5 开始,有 IReadOnlyListIReadOnlyCollection 都是协变的;后者基本上是IEnumerable加上Count;前者增加了T this[int index] {get;}.还应该注意的是,IEnumerable 从 .NET 4.0 开始是协变的.

ListReadOnlyCollection(通过 List.AsReadOnly()) 实现这两个.

<小时>

只有当它只有一个 get 索引器时,它才能是协变的,即

public T this[int index] { get;}

但是所有主要的集合都有 {get;set;},这让这很尴尬.我不知道有什么就足够了,但是您可以包装它,即编写一个扩展方法:

var covariant = list.AsCovariant();

它是 IList 的包装器,它只公开 IEnumerableget 索引器......?应该只需要几分钟的工作...

公共静态类协方差{公共静态 IIndexedEnumerableAsCovariant<T>(这个 IList<T> 尾部){返回新的 CovariantList(tail);}私有类 CovariantList: IIndexedEnumerable{私有只读 IList尾巴;公共协变列表(IList尾){this.tail = 尾巴;}public T this[int index] { get { return tail[index];} }公共 IEnumeratorGetEnumerator() { return tail.GetEnumerator();}IEnumerator IEnumerable.GetEnumerator() { return tail.GetEnumerator();}public int Count { get { return tail.Count;} }}}公共接口 IIndexedEnumerable:IEnumerable{T this[int index] { get;}int计数{得到;}}

I would like a Covariant collection whose items can be retrieved by index. IEnumerable is the only .net collection that I'm aware of that is Covariant, but it does not have this index support.

Specifically, I'd like to do this:

List<Dog> dogs = new List<Dog>();

IEnumerable<Animal> animals = dogs;
IList<Animal> animalList = dogs; // This line does not compile

Now, I'm aware of why this is a problem. List implements ICollection that has an Add method. By up casting to IList of Animals, it would allow subsequent code to add any type of animal which is not allowed in the "real" List<Dog> collection.

So is anyone aware of a collection that supports index lookups that is also covariant? I would like to not create my own.

解决方案

Update: from .NET 4.5 onwards there is IReadOnlyList<out T> and IReadOnlyCollection<out T> which are both covariant; The latter is basically IEnumerable<out T> plus Count; the former adds T this[int index] {get;}. It should also be noted that IEnumerable<out T> is covariant from .NET 4.0 onwards.

Both List<T> and ReadOnlyCollection<T> (via List<T>.AsReadOnly()) implement both of these.


It can only be covariant if it only has a get indexer, i.e.

public T this[int index] { get; }

But all main collections have {get;set;}, which makes that awkward. I'm not aware of any that would suffice there, but you could wrap it, i.e. write an extension method:

var covariant = list.AsCovariant();

which is a wrapper around an IList<T> that only exposes the IEnumerable<T> and the get indexer...? should be only a few minutes work...

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; }
}

这篇关于协方差和 IList的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆