Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > .NET для новичков > Почему список (List<>) меняется сам по себе?


Автор: Cinot 16.12.2010, 11:56
Столкнулся с такой вот непонятной для себя проблемой: имеется список, дальше производятся какие-то действия, где этот список используется (скажем, просто упомянается), в результате чего этот самый главный список меняет свои значения! Как, почему это происходит и как сохранить первоначальное значение неизменным?

Вот набросал небольшой код-примерчик:

Код

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Collections;


namespace Temp2
{
    static class Program
    {
        /// <summary>
        /// Главная точка входа для приложения.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());

            List<string> list1 = new List<string>() { "1", "2", "3" };
            List<string> list2 = new List<string>() { "a", "b", "c", "d", "e" };
            List<string> list3 = new List<string>() { "14r", "22g", "31f", "4f" };
            List<IEnumerable> main_list = new List<IEnumerable>();
            main_list.Add(list1);
            main_list.Add(list2);
            main_list.Add(list3);



            List<IEnumerable> other_list = new List<IEnumerable>();
            int[] count = new int[] { 0, 2 };// массив номеров нужных элементов списка main_list
            //Добавляем в other_list нужные списки из главного списка main_list:
            for (int j = 0; j < count.Length; j++)
            {
                other_list.Add(main_list[count[j]]);
            }

            //Создаём список other_list_new, содержащий списки только с первыми двумя значениями:
            List<IEnumerable> other_list_new = new List<IEnumerable>();
            foreach (List<string> item in other_list)
            {
                item.RemoveRange(2, (item.Count - 2));
                other_list_new.Add(item);
                item.Clear();// Вот в этом месте почему-то изменяется main_list, хотя его никто не менял
            }

        }

    }
}


http://s1.ipicture.ru/
http://s2.ipicture.ru/
http://s1.ipicture.ru/

Автор: CYBERDREAM 16.12.2010, 12:04
у тебя обе колекции ссылаются на одни и те же объекты, поэтому когда модифицируешь их, меняются в обоих коллекциях

Автор: Cinot 16.12.2010, 13:05
Но как исправить ситуацию? Как более грамотно написать?

Автор: CYBERDREAM 16.12.2010, 13:07
забивать разные объекты (клонировать)

Автор: KelTron 16.12.2010, 13:19
Вызови метод ToList(), он создаст копию списка, она и будет помещена в other_list
Код

for (int j = 0; j < count.Length; j++)
            {
                other_list.Add(main_list[count[j]].ToList());
            }

Автор: Cinot 16.12.2010, 14:19
Цитата(CYBERDREAM @  16.12.2010,  13:07 Найти цитируемый пост)
забивать разные объекты (клонировать)

Если Вас не затруднит, можете привести небольшой пример на основе части кода примера?
Цитата(KelTron @  16.12.2010,  13:19 Найти цитируемый пост)
Вызови метод ToList(), он создаст копию списка, она и будет помещена в other_list

Ошибка    1    "System.Collections.IEnumerable" не содержит определения для "ToList" и не был найден метод расширения "ToList", принимающий тип "System.Collections.IEnumerable" в качестве первого аргумента (возможно, пропущена директива using или ссылка на сборку)

Автор: CYBERDREAM 16.12.2010, 14:34
Код

/// <summary>
/// Главная точка входа для приложения.
/// </summary>
[STAThread]
private static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());

    var list1 = new List<string> {"1", "2", "3"};
    var list2 = new List<string> {"a", "b", "c", "d", "e"};
    var list3 = new List<string> {"14r", "22g", "31f", "4f"};
    var main_list = new List<IEnumerable<String>> {list1, list2, list3};


    var other_list = new List<IEnumerable>();
    var count = new[] {0, 2}; // массив номеров нужных элементов списка main_list
    //Добавляем в other_list нужные списки из главного списка main_list:
    for (int j = 0; j < count.Length; j++)
    {

        other_list.Add(new List<String>(main_list[count[j]]));
    }

    //Создаём список other_list_new, содержащий списки только с первыми двумя значениями:
    var other_list_new = new List<IEnumerable>();
    foreach (List<string> item in other_list)
    {
        item.RemoveRange(2, (item.Count - 2));
        other_list_new.Add(item);
        item.Clear(); // Вот в этом месте почему-то изменяется main_list, хотя его никто не менял
    }
}

Автор: Cinot 16.12.2010, 16:04
Большое спасибо за внесённую ясность!

Автор: KelTron 16.12.2010, 17:47
Цитата(Cinot @  16.12.2010,  14:19 Найти цитируемый пост)
Ошибка    1    "System.Collections.IEnumerable" не содержит определения для "ToList" и не был найден метод расширения "ToList", принимающий тип "System.Collections.IEnumerable" в качестве первого аргумента (возможно, пропущена директива using или ссылка на сборку)

Ну using System.Linq; ессно надо.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)