这里有一类我写来解决这样的情景:
public class CovariantIListAdapter<TBase, TDerived> : IList<TBase>
where TDerived : TBase
{
private IList<TDerived> source;
public CovariantIListAdapter(IList<TDerived> source)
{
this.source = source;
}
public IEnumerator<TBase> GetEnumerator()
{
foreach (var item in source)
yield return item;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(TBase item)
{
source.Add((TDerived) item);
}
public void Clear()
{
source.Clear();
}
public bool Contains(TBase item)
{
return source.Contains((TDerived) item);
}
public void CopyTo(TBase[] array, int arrayIndex)
{
foreach (var item in source)
array[arrayIndex++] = item;
}
public bool Remove(TBase item)
{
return source.Remove((TDerived) item);
}
public int Count
{
get { return source.Count; }
}
public bool IsReadOnly
{
get { return source.IsReadOnly; }
}
public int IndexOf(TBase item)
{
return source.IndexOf((TDerived) item);
}
public void Insert(int index, TBase item)
{
source.Insert(index, (TDerived) item);
}
public void RemoveAt(int index)
{
source.RemoveAt(index);
}
public TBase this[int index]
{
get { return source[index]; }
set { source[index] = (TDerived) value; }
}
}
现在你可以这样写代码:
List<Dog> dogs = new List<Dog>();
dogs.Add(new Dog { Name = "Spot", MaximumBarkDecibals = 110 });
IEnumerable<Animal> animals = dogs;
IList<Animal> animalList = new CovariantIListAdapter<Animal, Dog>(dogs);
animalList.Add(new Dog { Name = "Fluffy", MaximumBarkDecibals = 120 });
的变化是两个列表中可见,因为没什么仍然只有1名单。适配器类仅传递通话,根据需要投射项目以实现所需的IList<TBase>
界面。
很明显,如果你添加了除狗之外的任何东西到animalList
,它会抛出一个异常,但这符合我的需求。
+1 ......缺乏只读在.NET(除了'IEnumerable')集合接口使得这几乎是不可能的,但我想这是一个常见的用途 - 或许有人提出了一个可行的解决方案。 – 2011-04-29 12:44:14
您可以使用IEnumerable <>和ElementAt()一起使用,尽管语法不会很漂亮。 – 2011-04-29 12:50:36