Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
63 / 62 / 11
Регистрация: 28.12.2011
Сообщений: 280
1

Использование анонимных методов внутри цикла foreach

26.10.2014, 00:30. Показов 1146. Ответов 4
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день, у меня возникла любопытная ситуация, поведение которой я не знаю как объяснить.
В общим есть такая строчка кода.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
            Communicator.instans.UsersInfo(ids,
                delegate(VKUserInfo[] vkInfo)
                {
                    lidersInfo.SetVkInfo(vkInfo);
                    foreach (var lid in lidersInfo.infoLider)
                    {
                        var vi = vkInfo.Where(a => a.id == lid.vkid).FirstOrDefault();
                        if (vi != null)
                        {
                            Debug.Log("лоад фото " + lid.nameDistrict);
                            LoadPhoto.Load(vi.photo50Url, delegate(Texture2D tx)
                            {
                                Debug.Log("loads " + lid.nameDistrict);
                                lid.photo = tx;
                            });
                        }
                    }
                });
в цикле перебираю массив - для каждого объекта вызываю функцию которая возвращает некоторый ответ, коий я и хочу присвоить этому объекту, естественно ответ приходит не сразу а спустя некоторое время (конкретно скачиваеться фото с сервера в контакте). Но дело в том что все 3 раза полученный ответ присваивается одному объекту который находился в конце списка. Это можно проследить из полученных логов.
Кликните здесь для просмотра всего текста

(Filename: C:/BuildAgent/work/d3d49558e4d408f4/artifacts/WebPlayerGenerated/UnityEngineDebug.cpp Line: 53)

лоад фото Центр

(Filename: C:/BuildAgent/work/d3d49558e4d408f4/artifacts/WebPlayerGenerated/UnityEngineDebug.cpp Line: 53)

лоад фото Побережье

(Filename: C:/BuildAgent/work/d3d49558e4d408f4/artifacts/WebPlayerGenerated/UnityEngineDebug.cpp Line: 53)

лоад фото Пригород

(Filename: C:/BuildAgent/work/d3d49558e4d408f4/artifacts/WebPlayerGenerated/UnityEngineDebug.cpp Line: 53)

loads Пригород

(Filename: C:/BuildAgent/work/d3d49558e4d408f4/artifacts/WebPlayerGenerated/UnityEngineDebug.cpp Line: 53)

loads Пригород

(Filename: C:/BuildAgent/work/d3d49558e4d408f4/artifacts/WebPlayerGenerated/UnityEngineDebug.cpp Line: 53)

loads Пригород

(Filename: C:/BuildAgent/work/d3d49558e4d408f4/artifacts/WebPlayerGenerated/UnityEngineDebug.cpp Line: 53)


из логов мы видим что 3 раза вызвали 1 метод и передали в качестве аргумента 3 функции, но вызывается только последняя. По моему такого поведения ожидать не стоило? Или как это объяснить?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
26.10.2014, 00:30
Ответы с готовыми решениями:

Использование анонимных методов
Анонимные методы используются, когда нужно создать метод для обработки какого-то события и больше...

Ошибка при использование цикла foreach
Всем доброго времени суток. Есть небольшая проблема с циклом foreach. Смысл ошибки я понимаю, но...

Использование методов у объекта в c:forEach JSTL
Есть jsp страница на которой я пытаюсь с помощью JSTL foreach вывести List<Student> list =...

использование цикла Foreach
Добрый день дорогие форумчане, у меня такой вопрос, я хочу использовать цикл Foreach в свои...

4
Эксперт .NET
5534 / 4298 / 1217
Регистрация: 12.10.2013
Сообщений: 12,332
Записей в блоге: 2
26.10.2014, 01:10 2
Good1101, насколько я помню, в данном типе цикла(foreach) объекты итерации поменять нельзя. Но у вас тут еще и анонимные методы... Думаю дело в цикле. Замените цикл на простой for(...) и проверьте результат.
0
63 / 62 / 11
Регистрация: 28.12.2011
Сообщений: 280
26.10.2014, 01:39  [ТС] 3
insite2012, спасибо за ответ, но просто смена на фор не помогла. Полный ответ я нашел вот тут - http://habrahabr.ru/post/141270/ Дело оказалось еще и в том какая версия C# используется, как я понял в 5й версий мой код бы сработал как и ожидалось, но по скольку у меня кажется С# 3.0 то вот так. В итоге я все таки и сделал в for но и там пришлось сделать копию интексатора.
C#
1
2
3
4
5
6
7
8
9
10
11
12
        for (int i = 0; i < lidersInfo.infoLider.Count; i++)
        {      
            var vi = vkInfo.Where(a => a.id == lidersInfo.infoLider[i].vkid).FirstOrDefault();
            if (vi != null)
            {
                var current = i; //без этого действа во время обратного вызова i всегда будет 3 (в моем случае)
                LoadPhoto.Load(vi.photo50Url, delegate(Texture2D tx)
                {      
                    lidersInfo.infoLider[current].photo = tx;
                });
            }
        }
0
2735 / 2041 / 380
Регистрация: 22.07.2011
Сообщений: 7,731
26.10.2014, 01:34 4
По моему все дело в Load , я так понимаю delegate(Texture2D tx) - функция обратного вызова , которая вызывается асинхронно из отдельного потока , созданного в Load-е. Соответственно , к моменту когда она вызывается , цикл уже завершился , и переменная lid равна его последнему элементу.
И про компилятор Вы верно подметили , вообще инструкции с анонимными методами и захватом переменных могут неожиданным образом разбираться компилятором.
В первом случае происходит недетерминированное исполнение , а вот когда Вы присвоили current = i; , компилятор создал уже другую - детерминированную конструкцию:
http://rsdn.ru/article/csharp/... .xml#ELHAC - тут как раз ваша история.
0
140 / 137 / 22
Регистрация: 16.02.2012
Сообщений: 453
26.10.2014, 13:20 5
Просто итерационную переменную нужно занести в отдельную переменную в цикле
var lid1 = lid;
и работать с ней. Это особенность анонимных методов.
0
26.10.2014, 13:20
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
26.10.2014, 13:20
Помогаю со студенческими работами здесь

Как в связном списке внутри цикла ForEach-Next элемент сделать текущим?
Совсем недавно начал изучать PureBasic, и столкнулся с проблемой, извиняюсь, если задача пустяк,...

Использование методов внутри класса
В классе определил метод: def getRandomId(self): offset = randint(0, len(self.offers))...

Аргументы консоли, переменные внутри цикла, имена методов и объектов
В продолжение к теме https://www.cyberforum.ru/java-j2se/thread1781948.html FatNinja, HOBATOP,...

Использование массивов внутри методов класса
Нужно сделать так, чтобы массив NextBrick можно было использовать в ShowNB. При этом Массив...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru