如何在不克隆的情况下复制 List<T>

Posted

技术标签:

【中文标题】如何在不克隆的情况下复制 List<T>【英文标题】:How to copy a List<T> without cloning 【发布时间】:2012-07-27 03:44:12 【问题描述】:

也许我错过了一些微不足道的东西。我有几个List&lt;T&gt;s,我需要他们的一个大列表,它是所有其他列表的联合。但我确实希望他们在那个大列表中的引用,而不仅仅是值/副本(不像我通常在 SO 上找到的许多问题)。

例如我有这个,

List<string> list1 = new List<string>  "a", "b", "c" ;
List<string> list2 = new List<string>  "1", "2", "3" ;

var unionList = GetThatList(list1, list2);

假设我在unionList 中得到了我想要的列表,那么这应该会发生:

unionList.Remove("a"); => list1.Remove("a");
unionList.Remove("1"); => list2.Remove("1");

//in other words
//
//unionList.Count = 4;
//list1.Count = 2;
//list2.Count = 2;

为了清楚起见,这通常发生在

unionList = list1; //got the reference copy.

但是我该如何处理第二个列表,list2 添加到unionList

我尝试了AddAddRange,但它们显然是克隆而不是复制。

unionList = list1;
unionList.AddRange(list2); //-- error, clones, not copies here.

foreach (var item in list2)

    unionList.Add(item); //-- error, clones, not copies here.

更新:我想我在问一些毫无意义的问题,并且在语言中本质上是不可能的......

【问题讨论】:

据我所知,“开箱即用”是不可能的。要么您创建自己的集合类型来包装其他集合(但这似乎不必要地复杂),或者您更可能想要重新考虑您的程序。 @KooKiz 是的,我明白了。我当然可以没有它,但我在想一种可能性.. 它似乎不适用于您的情况,但请记住,这取决于您创建列表的数据类型。如果它是 List(of T as Class) 那么默认情况下它将复制引用而不是克隆对象。我认为只有在使用原始类型(或可能的结构)时才会遇到您所描述的问题。 【参考方案1】:

我认为不存在任何这样的课程。你可以自己实现它。这是一个开始:

class CombinedLists<T> : IEnumerable<T> // Add more interfaces here.
                                        // Maybe IList<T>, but how should it work?

    private List<List<T>> lists = new List<List<T>>();

    public void AddList(List<T> list)
    
        lists.Add(list);
    

    public IEnumerator<T> GetEnumerator()
    
        return lists.SelectMany(x => x).GetEnumerator();
    

    IEnumerator IEnumerable.GetEnumerator()
    
        return GetEnumerator();
    

    public bool Remove(T t)
    
        foreach (List<T> list in lists)
        
            if (list.Remove(t))  return true; 
        
        return false;
    

    // Implement the other methods.

这里有一些代码可以用来测试它:

List<string> list1 = new List<string>  "a", "b", "c" ;
List<string> list2 = new List<string>  "1", "2", "3" ;
CombinedLists<string> c = new CombinedLists<string>();
c.AddList(list1);
c.AddList(list2);

c.Remove("a");
c.Remove("1");

foreach (var x in c)  Console.WriteLine(x); 
Console.WriteLine(list1.Count);
Console.WriteLine(list2.Count);

删除项目相当简单。但是,如果您尝试将项目插入组合列表中,您可能会遇到问题。并不总是明确定义哪个列表应该接收插入的项目。例如,如果您有一个包含两个空列表的组合列表,并且您在索引 0 处插入一个项目,该项目应该添加到第一个还是第二个空列表中?

【讨论】:

@nawfal 我很好奇。如果要添加项目怎么办? @KendallFrey,我还没有考虑过。事实上,我自己的问题也是出于好奇而不是要求。但是,是的,如果您添加到较小的列表中,我希望它会添加到 unionlist。但是,如果将其添加到 unionlist,那么正确的选择是在子列表中忽略它。马克的回答是这样处理的,因为 public Add 方法没有定义:D @MarkByers,更加好奇,如果我必须将项目添加到子列表中会怎样?有没有办法反映在 unionlist 中? @nawfal:如果您将项目添加到子列表中,它将在联合列表中可用。但问题是,如果您尝试将元素直接添加到联合列表中。如果有的话,它应该出现在哪个子列表中? @nawfal:密钥是SelectMany

以上是关于如何在不克隆的情况下复制 List<T>的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用复制或克隆的情况下克隆Rust中的结构?

如何在不使用 JSON.stringify 或 JSON.parse 的情况下在 javascript 中克隆数组? [复制]

如何在不调用渲染函数的情况下访问 Context 的值? [复制]

如何在没有 foreach 的情况下将项目从列表复制到列表?

如何在不复制的情况下从 N 维容器中获取可迭代范围?

如何对 IList<T> 执行二进制搜索?