C #: как правильно клонировать список <> для других

1

У меня есть два списка: оригинал, другой - копия оригинала

    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);
        }

в вышеупомянутых трех ситуациях оба списка сортируются :( Я хочу просто отсортировать только экземплярButtonList, может ли кто-нибудь указать мои ошибки, которые я здесь сделал?

Обновлено: мой алгоритм сортировки вставки ниже

 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;
    }
  • 4
    Все 3 метода поверхностного клонирования списка верны. Вы проблема в другом месте.
  • 0
    @ Атари прав ... Что ты хочешь делать с копией?
Показать ещё 4 комментария
Теги:
generics
list
collections
clone

3 ответа

0
Лучший ответ

Собственно говорящий вопрос не тупой. Поскольку вы не меняете 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();

}

Это печатает

аа

куб.см

бб

а потом

аа

бб

куб.см

Обновить

Ваш ARE меняет кнопку, поэтому вам нужна глубокая копия. Используйте это, чтобы создать новый список.

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

В чем разница между ссылочным типом и типом значения в С#?

Также запустите на своем компьютере следующее консольное приложение и посмотрите, что напечатано

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" и посмотрите, что напечатано.

Вы получаете другой результат, потому что структуры - типы значений, а классы - ссылочные типы.

  • 0
    Это нормально, но все же я не могу понять проблему моего кода
  • 0
    Ваша проблема в том, что вы меняете кнопки во вставке сортировки
Показать ещё 2 комментария
0

Ваш алгоритм сортировки изменяет кнопки, которые одинаковы в обоих списках. если вы действительно хотите это сделать, вам нужно глубоко скопировать объекты, т.е. делать копии или каждую кнопку, а не только их ссылки.

но гораздо лучшим решением для сортировки списка было бы просто отсортировать список, т.е. переключите индексы элементов. (например, button[i+1]=button[i])

0

Вы можете использовать метод, упомянутый здесь

List<YourType> oldList = new List<YourType>();
List<YourType> newList = new List<YourType>(oldList.Count);

oldList.ForEach((item)=>
    {
        newList.Add(new YourType(item));
    });
  • 4
    Если OP борется с базовыми вещами, использование ForEach и лямбда вместо foreach , вероятно, является плохой идеей.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню