【问题标题】:C# : how do I correctly clone a List<> to ontherC#:如何正确地将 List<> 克隆到另一个
【发布时间】:2014-10-22 19:11:27
【问题描述】:

我有两个列表,一个是原始的,另一个是原始列表的副本

    List<Button> buttonList; // this is the original list
    List<Button> copyButtonList;// this is the copy of button list; this use to sort the list

我想根据我在单独类中编写的自定义插入排序对copyButtonList 进行排序

我按照以下方式克隆原始列表以复制列表并对其进行排序

        copyButtonList = buttonList.ToList();

        String s = SortEngine.insertionSort(copyButtonList); 
        msgList.Items.Add(s);

我也尝试以下方法

        copyButtonList = new List<Button>(buttonList);

foreach (var b in buttonList) {
            copyButtonList.Add(b);
        }

之后我尝试按如下方式打印这两个列表

foreach(var b in buttonList){
            msgList.Items.Add(b.Text);
        }
        foreach(var b in copyButtonList){
            msgList.Items.Add(b.Text);
        }

在上述三种情况下,两个列表都是排序的:( 我只想对copyButtonList进行排序,谁能指出我在这里做的错误?

更新:我的插入排序算法如下

 public static String insertionSort(List<Button> button)
    {
        String key;
        int i = 0;
        int j;
        String s = "";
        for (j = 1; j < button.Count; j++)
        {
            key = button.ElementAt(j).Text;
            i = j - 1;
            while (i >= 0 && int.Parse(button.ElementAt(i).Text) > int.Parse(key))
            {
                button.ElementAt(i + 1).Text = button.ElementAt(i).Text;

                i = i - 1;

            }
            button.ElementAt(i + 1).Text = key;
            if (i == -1)
            {

                s=(button.ElementAt(i + 1).Text + " is the starting Item, keep this in before " + button.ElementAt(i + 2).Text);

            }
            else if (i == j - 1)
            {
                s=(button.ElementAt(i + 1).Text + " is the last Item, keep this in after  " + button.ElementAt(i).Text);

            }
            else
            {
                s=(button.ElementAt(i + 1).Text + " is between " + button.ElementAt(i).Text + " and " + button.ElementAt(i + 2).Text);

            }

        }

        if (button.Count == 1)
        {
            s= ("This is the first Item");
        }
        return s;
    }

【问题讨论】:

  • 列表的3种浅克隆方法都是正确的。你的问题出在其他地方。
  • @Athari 是对的......你想对副本做什么?
  • 愚蠢的问题:您是否在排序之前验证了两个列表的排序顺序?
  • 哦!另一个愚蠢的问题:您的insertionSort 是如何实现的?你交换文本而不是列表中的索引位置吗?
  • @Andre 我只想对副本进行排序而不影响原件

标签: c# list generics collections clone


【解决方案1】:

其实speising的问题并不傻。 由于您没有更改 Button,因此不需要进行深度克隆。 您的问题可能在其他地方。 这是一个例子

public class Customer
{
    public string Name { get; set; }

    public override string ToString()
    {
        return Name; 
    }
}

public class CustomerComparer : IComparer<Customer>
{
    public int Compare(Customer x, Customer y)
    {
        return x.Name.CompareTo(y.Name);
    }
}


void Print()
{

   List<Customer> l1 = new List<Customer>();
   l1.Add(new Customer() {  Name="aa"});
   l1.Add(new Customer() { Name = "cc" });
   l1.Add(new Customer() { Name = "bb" });

   List<Customer> l2 = new List<Customer>(l1);


   l2.Sort(new CustomerComparer());
   foreach (var item in l1)
        Console.WriteLine(item);


   Console.WriteLine();
   foreach (var item in l2)
        Console.WriteLine(item);

   Console.ReadLine();

}

打印出来

抄送

bb

然后

bb

抄送

更新

您正在更改按钮,因此您需要一个深层副本。使用它来创建新列表

using System.Linq;
copyButtonList = buttonList.Select(ee => new Button() {  Text= ee.Text}).ToList();

“更改按钮”是指这样的行

button.ElementAt(i + 1).Text = key;

您可能有 2 个列表,但它们都“指向”/具有相同的对象。当您更改列表 1 中按钮的文本时,这意味着列表 2 中的对象也发生了更改。

您需要了解什么是值类型,什么是引用类型以及它们的区别。以下是一些对您有帮助的链接

http://www.albahari.com/valuevsreftypes.aspx

What is the difference between a reference type and value type in c#?

同时在您的电脑上运行以下控制台应用程序并查看打印的内容

using System;

public struct Point
{
  public int X;
  public Point(int initialValue) { X = initialValue; }
}

class Program
{

  static void Main(string[] args)
  {

    Point point1 = new Point(5);

    Console.WriteLine("Before:" + point1.X);
    ChangePoint(point1);
    Console.WriteLine("After:" + point1.X);
    Console.ReadLine();
  }

  private static void ChangePoint(Point p)
  {
    p.X = 20;
  }
}

然后只需将单词“struct”更改为“class”,然后查看打印的内容。

你会得到不同的结果,因为结构是值类型而类是引用类型。

【讨论】:

  • 这很好,但我仍然无法弄清楚我的代码的问题
  • 您的问题是您正在更改插入排序中的按钮
  • 嘿亲爱的,你能解释一下你的解释中“你正在改变按钮”这个术语吗,我想一次复制一个元素到另一个列表并做一些操作,然后添加另一个元素到那个列表并做一些明智的操作。我仍然无法理解这里使用的深层副本
【解决方案2】:

您的排序算法修改了两个列表中的按钮。如果你真的想这样做,你需要深度复制对象,即。制作副本或每个按钮,而不仅仅是它们的参考。

但是对列表进行排序的更好的解决方案是对列表进行排序,即。切换元素索引。 (如button[i+1]=button[i]

【讨论】:

    【解决方案3】:

    您可以使用here提到的方法

    List<YourType> oldList = new List<YourType>();
    List<YourType> newList = new List<YourType>(oldList.Count);
    
    oldList.ForEach((item)=>
        {
            newList.Add(new YourType(item));
        });
    

    【讨论】:

    • 如果 OP 在基本的东西上苦苦挣扎,使用 ForEach 和 lambdas 而不是 foreach 可能是个坏主意。
    猜你喜欢
    • 2012-03-26
    • 2016-05-18
    • 2017-05-19
    • 2014-04-29
    • 1970-01-01
    • 1970-01-01
    • 2011-04-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多