是否可以仅克隆 List<T>
的一部分?
示例:
List<string> myoriginalstring = new List<string>();
myoriginalstring.Add("Tyrannosaurus");
myoriginalstring.Add("Amargasaurus");
myoriginalstring.Add("Mamenchisaurus");
我想克隆myoriginalstring
到另一个列表,但仅来自索引 1
到索引2
.
这可能吗?第二个变化List<string>
应该首先体现出来,反之亦然。
更新
感谢您迄今为止的回答。看来我没有正确表达自己的意思。
其实我不想复制或克隆。我需要创建一个新列表(这将是原始列表的一部分);当我更改新列表中的某些内容(某些值)时,原始列表也应该以相同的方式更改。 (列表应该始终相同,只是新列表将是原始列表的一部分)。
希望这更清楚。
最佳答案
您可以创建 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"
.
关于c# - 如何克隆列表的一部分?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26495500/