我想制作一个列表的只读可索引“视图”,稍微扭曲只读视图应该枚举到列表类型的接口。
interface IIndexable<out T> : IEnumerable<T>
{
T this[int i] { get; }
int Count { get; }
}
使用场景看起来像这样。
List<Dog> dogs = new List<Dog>[]{ dog1, dog2 }; // Dog implements IAnimal
IIndexable<IAnimal> animals = dogs.AsIIndexable<Dog, IAnimal>();
IAnimal first = animals[0];
我认为考虑到协方差和类型约束,这是可能的,但也许我在这里弄错了。我的第一次尝试看起来像这样,由于枚举器的类型,它不起作用。
internal class ListIndexable<TC, T> : IIndexable<T> where TC : T
{
private List<TC> list;
public ListIndexable(List<TC> list) { this.list = list; }
public T this[int i] { get { return list[i]; } }
public IEnumerator<T> GetEnumerator()
{
return list.GetEnumerator(); // Computer says no.
}
}
为什么我不能IEnumerator<TC>
作为一个返回IEnumerator<T>
?类型是协变的,我用 TC 对其进行了约束:T。返回 an 真的不安全IEnumerator<TC>
,还是编译器的推理忽略类型约束只是一个弱点?
我可以通过使用自定义枚举器来解决它,该枚举器将其包装IEnumerator<TC>
并将其项目返回为T
's,这当然是完全合法的,但我只是好奇为什么上述解决方案不起作用。
internal class ListIndexable<TC, T> : IIndexable<T> where TC : T
{
private List<TC> list;
public ListIndexable(List<TC> list) { this.list = list; }
public T this[int i] { get { return list[i]; } }
public IEnumerator<T> GetEnumerator()
{
return new Enumerator(list.GetEnumerator());
}
class Enumerator : IEnumerator<T>
{
private IEnumerator<TC> inner;
internal Enumerator(IEnumerator<TC> inner) { this.inner = inner; }
public bool MoveNext()
{
return inner.MoveNext();
}
public T Current
{
get { return inner.Current; }
}
// ...
}
}