您可以创建一个ListSlice<T> 类来表示现有列表的一部分。切片将表现为只读列表,并且因为它保留对原始列表的引用,所以您不应该在原始列表中添加或删除元素。除非您实现自己的列表,否则无法强制执行此操作,但我不会在这里执行。
您必须实现整个IList<T> 接口,包括枚举切片所需的IEnumerator<T>。这是一个例子:
class ListSlice<T> : IList<T> {
readonly IList<T> list;
readonly Int32 startIndex;
readonly Int32 length;
public ListSlice(IList<T> list, Int32 startIndex, Int32 length) {
if (list == null)
throw new ArgumentNullException("list");
if (!(0 <= startIndex && startIndex < list.Count))
throw new ArgumentException("startIndex");
if (!(0 <= length && length <= list.Count - startIndex))
throw new ArgumentException("length");
this.list = list;
this.startIndex = startIndex;
this.length = length;
}
public T this[Int32 index] {
get {
if (!(0 <= index && index < this.length))
throw new ArgumentOutOfRangeException();
return this.list[this.startIndex + index];
}
set {
if (!(0 <= index && index < this.length))
throw new ArgumentOutOfRangeException();
this.list[this.startIndex + index] = value;
}
}
public Int32 IndexOf(T item) {
var index = this.list.IndexOf(item);
return index == -1 || index >= this.startIndex + this.length
? -1 : index - this.startIndex;
}
public void Insert(Int32 index, T item) { throw new NotSupportedException(); }
public void RemoveAt(Int32 index) { throw new NotSupportedException(); }
public Int32 Count { get { return this.length; } }
public Boolean IsReadOnly { get { return true; } }
public void Add(T item) { throw new NotSupportedException(); }
public void Clear() { throw new NotSupportedException(); }
public Boolean Contains(T item) { return IndexOf(item) != -1; }
public void CopyTo(T[] array, Int32 arrayIndex) {
for (var i = this.startIndex; i < this.length; i += 1)
array[i + arrayIndex] = this.list[i];
}
public Boolean Remove(T item) { throw new NotSupportedException(); }
public IEnumerator<T> GetEnumerator() {
return new Enumerator(this.list, this.startIndex, this.length);
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
class Enumerator : IEnumerator<T> {
readonly IList<T> list;
readonly Int32 startIndex;
readonly Int32 length;
Int32 index;
T current;
public Enumerator(IList<T> list, Int32 startIndex, Int32 length) {
this.list = list;
this.startIndex = startIndex;
this.length = length;
}
public T Current { get { return this.current; } }
Object IEnumerator.Current {
get {
if (this.index == 0 || this.index == this.length + 1)
throw new InvalidOperationException();
return Current;
}
}
public Boolean MoveNext() {
if (this.index < this.length) {
this.current = this.list[this.index + this.startIndex];
this.index += 1;
return true;
}
this.current = default(T);
return false;
}
public void Reset() {
this.index = 0;
this.current = default(T);
}
public void Dispose() {
}
}
}
您可以编写一个扩展方法来更轻松地使用切片:
static class ListExtensions {
public static ListSlice<T> Slice<T>(this IList<T> list, Int32 startIndex, Int32 length) {
return new ListSlice<T>(list, startIndex, length);
}
}
要使用切片,您可以编写如下代码:
var list = new List<String> {
"Tyrannosaurus",
"Amargasaurus",
"Mamenchisaurus"
};
var slice = list.Slice(1, 2);
slice[0] = "Stegosaurus";
现在list[1] 和slice[0] 包含"Stegosaurus"。