Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / присвоение внутри foreach / 15 сообщений из 15, страница 1 из 1
31.05.2014, 18:18
    #38657746
Lamo2012
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
присвоение внутри foreach
Есть код:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var list = new List<MyClass>();
            for (int i = 0; i < 10; i++)
            {
                list.Add(new MyClass { Id = i, Property = i + 10 });
            }

            var list2 = list.Select(x => new MyClass { Id = x.Id, Property = x.Property });

            foreach (var item in list2)
            {
                item.Property = 777;
            }

            foreach (var item in list2)
            {
                Console.WriteLine(item.Property);
            }

            Console.ReadKey();
        }
    }

    class MyClass
    {
        public int Id { get; set; }
        public int Property { get; set; }
    }
}


Почему при выводе на экран item.Property не равно 777?!
...
Рейтинг: 0 / 0
31.05.2014, 18:28
    #38657749
VSVLAD
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
присвоение внутри foreach
Lamo2012,

foreach создает копию итератора для перечисления, не желательно вообще проводить такие манипуляции и удаления итемов в For Each
...
Рейтинг: 0 / 0
31.05.2014, 18:40
    #38657753
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
присвоение внутри foreach
Lamo2012, всё дело в этой строке
Код: c#
1.
var list2 = list.Select(x => new MyClass { Id = x.Id, Property = x.Property });


list2 имеет тип IEnumerable<MyClass> и так как ты в Select создаешь новый экзмепляр list, то при выполнении foreach каждый раз создаются новые - временные - экземпляры MyClass. Чтобы получить ожидаемое поведение нужно превратить временную коллекцию в постоянную с помощью ToList()/ToArray
Код: c#
1.
var list2 = list.Select(x => new MyClass { Id = x.Id, Property = x.Property }).ToList();


или убрать создание копии MyList:
Код: c#
1.
var list2 = list.Select(x => x);
...
Рейтинг: 0 / 0
31.05.2014, 18:41
    #38657754
VSVLAD
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
присвоение внутри foreach
хотя возможно вру....
...
Рейтинг: 0 / 0
31.05.2014, 21:18
    #38657796
Lamo2012
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
присвоение внутри foreach
bazile... Чтобы получить ожидаемое поведение нужно превратить временную коллекцию в постоянную с помощью ToList()/ToArray

Спасибо, помогло. Я наивно думал что foreach просто вызовет отложенное выполнение list.Select(x => new MyClass { Id = x.Id, Property = x.Property }) и присвоение его list2 а потом переберет list2 и присвоит нужные значения свойству. Но вот копирование содержимого списка это для меня сюрприз. Зачем он это делает?!
...
Рейтинг: 0 / 0
31.05.2014, 22:23
    #38657816
Где-то в степи
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
присвоение внутри foreach
Lamo2012,
автор Я наивно думал что foreach просто вызовет отложенное выполнение list.Select(x => new MyClass { Id = x.Id, Property = x.Property })
он просто и вызывает.
авторНо вот копирование содержимого списка это для меня сюрприз. Зачем он это делает?!
где вы увидели копирование ?
попробуйте указать явно тип переменной list2 в коде, а не прикрываться что компилятор выведет,( он то знает все)
а после этого посмотреть что это за тип в справке, и как он работает..
...
Рейтинг: 0 / 0
31.05.2014, 22:31
    #38657820
zz
zz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
присвоение внутри foreach
Lamo2012 Но вот копирование содержимого списка это для меня сюрприз. Зачем он это делает?!
Потому что нету никакого списка.
Есть IEnumerable<T>.
У которого foreach дергает GetEnumerator<T>.
Который честным образом выполняет x => new MyClass, т.е и создает копию.

Сколько раз foreach, столько раз GetEnumerator, столько и копий.
...
Рейтинг: 0 / 0
31.05.2014, 22:57
    #38657828
Где-то в степи
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
присвоение внутри foreach
zz,авторт.е и создает копию.
скорее создают объект на основе данных другого объекта, ( то что типы объектов совпадают, чистая случайность автора кода)
копирование тут как бы не уместно, вообще как бы надо поосторожней с терминами, я вот в соседнем топике
рассмотрел локальные переменные с точки зрения стека, а ведь это не прально, 90 процентов диезников и не знает что это, да и ненужно это им, тут как бы другое определение локальных переменных надо ( более народное)
...
Рейтинг: 0 / 0
31.05.2014, 23:16
    #38657842
Где-то в степи
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
присвоение внутри foreach
VSVLAD,
авторне желательно вообще проводить такие манипуляции и удаления итемов в For Each
врете )) природа переменной итерации readonly
...
Рейтинг: 0 / 0
01.06.2014, 08:55
    #38657920
Lamo2012
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
присвоение внутри foreach
zz...Есть IEnumerable<T>.
У которого foreach дергает GetEnumerator<T>.
Который честным образом выполняет x => new MyClass, т.е и создает копию.
Сколько раз foreach, столько раз GetEnumerator, столько и копий.

Т.е. получается я сам себя ввел в заблуждение именами своих переменных. В list2 у меня совсем не лист, а дерево выражений (так оно правильно вроде называется), которое выполняется при каждом foreach, честно создавая мне все новые копии айтемов исходного list. Я правильно понял?
...
Рейтинг: 0 / 0
01.06.2014, 21:33
    #38658143
Lelouch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
присвоение внутри foreach
Lamo2012,

Деревья выражений строятся для IQueryable) У вас там IEnumerable обертка, итератор которой для каждого элемента вызывает вот эту ф-ию: x => new MyClass { Id = x.Id, Property = x.Property }
...
Рейтинг: 0 / 0
02.06.2014, 10:14
    #38658319
zz
zz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
присвоение внутри foreach
Lamo2012В list2 у меня совсем не лист, а дерево выражений (так оно правильно вроде называется), которое выполняется при каждом foreach, честно создавая мне все новые копии айтемов исходного list. Я правильно понял?

У Вас какая-то путаница с понятиями.

Изначально имеет list1 с типом List<MyClass>. Поскольку List<MyClass> реализует интерфейс IEnumerable<MyClass>, у него есть метод GetEnumerator<MyClass>, который возвращает итератор по объекту list1.

Далее Вы вот этим выражением

var list2 = list.Select(x => new MyClass { Id = x.Id, Property = x.Property });

создали объект IEnumerable<MyClass> с измененным , по отношению к list, итератором. Что же изменилось в этом итераторе? Изменился метод MoveNext, который стал звучать примерно так:

"При запросе следующего элемента последовательности верни мне, пожалуйста, новый экземпляр MyClass".

Эта инструкция зафиксирована в качестве параметра метода Select, и она является лямбда-выражением (но не деревом выражений). Дерево выражений было бы параметром метода Select, если бы он относился к объекту типа IQueryable, как уже справедливо отметили выше.


Вас, скорее всего, смущает "ленивость" происходящих операций, дескать - а почему преобразование выполняется не "мгновенно", а отложенно. А потому, что оно не должно выполняться. Грубо говоря, Вы меняете закон получения последовательности. А выполняется этот закон в момент перебора последовательности. Можно "зафиксировать" этот закон, выполнив метод ToList(), про что тоже уже говорили выше.
...
Рейтинг: 0 / 0
02.06.2014, 11:36
    #38658402
Где-то в степи
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
присвоение внутри foreach
zz,
авторУ Вас какая-то путаница с понятиями
Проблема не нова, я думаю процентов 50 не вкуривают что это такое, я ( честно) встречал руководителей проектов, которые так и представляли
что перчисление это указатель на кучу где лежит какая то последовательность, и публично это оспаривали, а на мой
аргумент
автор while (true)
{
yield return 1000;
}

говорили что так делать нельзя ( не хватит памяти у компьютера...), и что интересно, они справлялись со своей задачей и делали балоемкие проекты..., так что имхо одно другому не мешает, особенно в ASP.net.

>Lamo2012
Lamo2012 новые копии айтемов исходного list.
Вот это как серпом по яицам, ну если копия докажите что o1 копия o2,
...
Рейтинг: 0 / 0
02.06.2014, 14:18
    #38658739
Lelouch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
присвоение внутри foreach
zz,

и чем ваша простыня сильно отличается от моего предложения? я в курсе, что логика находится в итераторе, основной посыл сообщения был в том, что для списков не строятся деревья выражений.

zzВас, скорее всего, смущает "ленивость" происходящих операций, дескать - а почему преобразование выполняется не "мгновенно", а отложенно.

Меня она совершенно не смущает и никогда не смущала. А должна?
...
Рейтинг: 0 / 0
02.06.2014, 14:21
    #38658746
Lelouch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
присвоение внутри foreach
zz,
извините, показалось, что вы отвечали мне.
...
Рейтинг: 0 / 0
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / присвоение внутри foreach / 15 сообщений из 15, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]