我需要两个独立的列表和一个包含这两个列表项的列表。
List<int> list1 = new List<int>();
List<int> list2 = new List<int>();
List<int> list3 = list1 & list2
当我在list1中添加一些整数时,我希望它们也出现在list3中。 将新项目添加到list2时,我想要相同的行为。
多个列表的引用。
这可能吗?
答案 0 :(得分:8)
不,你不能直接用List<T>
做到这一点。但是,您可以声明:
IEnumerable<int> union = list1.Union(list2);
现在将进行延迟评估 - 每次迭代union
时,它将返回list1
或list2
(或两者)中的每个整数。它只返回任何一次整数。
如果您想要等效但具有连接,则可以使用
IEnumerable<int> concatenation = list1.Concat(list2);
同样,这将被懒惰地评估。
如注释中所述,这并未公开List<T>
所做的所有操作,但是如果您只需要读取“组合整数”(并且以迭代方式而不是以某种随机访问方式进行)那可能就是你所需要的一切。
答案 1 :(得分:2)
有可能吗?
不是List
,因为它是静态数据结构 - 但是您可以使用查询,它是两个列表的串联。然后,无论何时枚举查询,它都会显示当前内容:
List<int> list1 = new List<int>();
List<int> list2 = new List<int>();
IEnumerable<int> list3 = list1.Concat(list2);
但是只要将查询实现为数据结构(通过调用ToList
,ToArray
等),内容就是静态的,如果其中一个基础列表更新,则不会更新。 / p>
答案 2 :(得分:2)
没有。您可以创建自己的自定义类型,公开类似于List<T>
所做的方法(索引器,Add
,Remove
方法等),甚至可能实现IList<T>
,但它不是List<T>
。
public class CompositeList<T> : IList<T>
{
private IList<IList<T>> lists;
public CompositeList(IList<IList<T>> lists)
{
this.lists = lists;
}
public CompositeList(params IList<T>[] lists)
{
this.lists = lists;
}
public int IndexOf(T item)
{
int globalIndex = 0;
foreach (var list in lists)
{
var localIndex = list.IndexOf(item);
if (localIndex >= 0)
return globalIndex + localIndex;
else
globalIndex += list.Count;
}
return -1;
}
public void Insert(int index, T item)
{
//note that there is an ambiguity over where items should be inserted
//when they are on the border of a set of lists.
foreach (var list in lists)
{
//use greater than or equal instead of just greater than to have the inserted item
//go in the later of the two lists in ambiguous situations,
//rather than the former.
if (index > list.Count)
index -= list.Count;
else
{
list.Insert(index, item);
return;
}
}
//TODO deal with having no lists in `lists`
//TODO deal with having only empty lists in `lists`
throw new IndexOutOfRangeException();
}
public void RemoveAt(int index)
{
foreach (var list in lists)
{
if (index > lists.Count)
index -= list.Count;
else
list.RemoveAt(index);
}
throw new IndexOutOfRangeException();
}
public T this[int index]
{
get
{
foreach (var list in lists)
{
if (index > lists.Count)
index -= list.Count;
else
return list[index];
}
throw new IndexOutOfRangeException();
}
set
{
foreach (var list in lists)
{
if (index > lists.Count)
index -= list.Count;
else
list[index] = value;
}
throw new IndexOutOfRangeException();
}
}
public void Add(T item)
{
if (!lists.Any())
lists.Add(new List<T>());
lists[lists.Count - 1].Add(item);
}
public void Clear()
{
foreach (var list in lists)
list.Clear();
}
public bool Contains(T item)
{
return lists.Any(list => list.Contains(item));
}
public void CopyTo(T[] array, int arrayIndex)
{
if (array.Length - arrayIndex - Count < 0)
throw new ArgumentException("The array is not large enough.");
int iterations = Math.Min(array.Length, Count);
for (int i = arrayIndex; i < iterations; i++)
array[i] = this[i];
}
public int Count
{
get { return lists.Sum(list => list.Count); }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(T item)
{
foreach (var list in lists)
{
if (list.Remove(item))
return true;
}
return false;
}
public IEnumerator<T> GetEnumerator()
{
return lists.SelectMany(x => x).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}