Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.71/7: Рейтинг темы: голосов - 7, средняя оценка - 4.71
Заблокирован

Выносить ли лямбду из цикла?

15.03.2018, 10:12. Показов 1457. Ответов 12
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
C#
1
2
3
4
5
var lambda = x => x <= 10;
for (var i = 0; i < N; i++)
{
    doSomething(i, lambda);
}
или
C#
1
2
3
4
for (var i = 0; i < N; i++)
{
    doSomething(i, x => x <= 10);
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
15.03.2018, 10:12
Ответы с готовыми решениями:

Разобрать лямбду
Здравствуйте. Есть вот такая строка: return result.Take ( 3 ).Where ( res =&gt; res.Result &lt; ( isCalibration ?...

Преобразование в лямбду
Hello World! Дано условие. Создайте лямбду isIllegalString, принимающую множество символов и строку, проверяющую, содержит ли...

Так правильно выносить?
Подскажите пожалуйста (sin(a)*cos(x)+cos(a)*sin(x))...

12
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
15.03.2018, 10:48
В данном случае — без разницы.
1
Заблокирован
15.03.2018, 12:27  [ТС]
kolorotur, во втором случае, я думаю, получается будет создаваться каждый раз новая лямбда. А в первом варианте мы, так сказать, закешировали её.
0
 Аватар для CpamJIo
28 / 28 / 15
Регистрация: 06.12.2017
Сообщений: 48
15.03.2018, 12:46
Лучший ответ Сообщение было отмечено pgrestorator1 как решение

Решение

Если не ошибаюсь, функтор или лямбду в неявном виде вы не сможете скомпилировать.

Ответ: Стоит выносить.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
            Stopwatch sw = new Stopwatch();
            sw.Start();
           Func<int,bool> lambda =( x => x <= 10);
 
           for(int i=0; i<1000000; i++)
            {
                DoSomething(i , lambda);
            }
 
            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds); // 8 миллисекунд 
 
            sw = new Stopwatch();
            sw.Start();
 
            for (int i = 0; i < 1000000; i++)
            {
                DoSomething(i , ( x => x <= 10 ));
            }
 
            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds); // 9 миллисекунд
1
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
15.03.2018, 12:56
Лучший ответ Сообщение было отмечено pgrestorator1 как решение

Решение

Цитата Сообщение от pgrestorator1 Посмотреть сообщение
во втором случае, я думаю, получается будет создаваться каждый раз новая лямбда.
Нет, не будет.

Цитата Сообщение от CpamJIo Посмотреть сообщение
8 миллисекунд
Цитата Сообщение от CpamJIo Посмотреть сообщение
9 миллисекунд
Шум.

В обоих случаях делегат создается ровно один раз и повторно используется.

Добавлено через 4 минуты
Наверное, надо все-таки оговориться, что я рассматриваю конкретно этот сценарий и предполагаю, что он компилируется на МСовском компиляторе, который в данном случае кэширует делегат.
В других случаях или на других компиляторах кэширования может и не быть и делегат будет создаваться каждый раз в цикле.
0
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
15.03.2018, 13:21
pgrestorator1, на практике, особенно в linq, никто не выносит лямды в переменные, т.к. такой код сложнее читать.
0
 Аватар для CpamJIo
28 / 28 / 15
Регистрация: 06.12.2017
Сообщений: 48
15.03.2018, 13:33
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
35
36
37
38
39
40
    // loop start (head: IL_0033)
        IL_0025: nop
        IL_0026: ldloc.0
        IL_0027: ldloc.1
        IL_0028: callvirt instance !1 class [mscorlib]System.Func`2<int32, bool>::Invoke(!0)
        IL_002d: pop
        IL_002e: nop
        IL_002f: ldloc.1
        IL_0030: ldc.i4.1
        IL_0031: add
        IL_0032: stloc.1
 
        IL_0033: ldloc.1
        IL_0034: ldc.i4 10000000
        IL_0039: clt
        IL_003b: stloc.2
        IL_003c: ldloc.2
        IL_003d: brtrue.s IL_0025
    // end loop
 
 
    // loop start (head: IL_0051)
        IL_0043: nop
        IL_0044: ldloc.0
        IL_0045: ldloc.3
        IL_0046: callvirt instance !1 class [mscorlib]System.Func`2<int32, bool>::Invoke(!0)
        IL_004b: pop
        IL_004c: nop
        IL_004d: ldloc.3
        IL_004e: ldc.i4.1
        IL_004f: add
        IL_0050: stloc.3
 
        IL_0051: ldloc.3
        IL_0052: ldc.i4 10000000
        IL_0057: clt
        IL_0059: stloc.s 4
        IL_005b: ldloc.s 4
        IL_005d: brtrue.s IL_0043
    // end loop
Таки да. В моем примере выше используется только один функтор

А если по отдельности, то в IL функтор создается каждую итерацию при стандартном компиляторе.
Мой ответ остается прежним.
3
Заблокирован
15.03.2018, 13:33  [ТС]
Wolfdp, по-поводу linq полностью согласен, там своя атмосфера

CpamJIo, благодарю за проведенный бенч. В крайнем ответе это msil под рефлектором?
0
 Аватар для CpamJIo
28 / 28 / 15
Регистрация: 06.12.2017
Сообщений: 48
15.03.2018, 13:41
Цитата Сообщение от pgrestorator1 Посмотреть сообщение
В крайнем ответе это msil под рефлектором?
Да.

Вариант с выносом функтора за пределы цикла
Кликните здесь для просмотра всего текста

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
35
36
37
38
    // Func<int, bool> lambda = (int x) => x <= 10;
    IL_0017: ldsfld class ConsoleApplication.Program/'<>c' ConsoleApplication.Program/'<>c'::'<>9'
    IL_001c: ldftn instance bool ConsoleApplication.Program/'<>c'::'<Main>b__1_0'(int32)
    // (no C# code)
    IL_0022: newobj instance void class [mscorlib]System.Func`2<int32, bool>::.ctor(object, native int)
    IL_0027: dup
    IL_0028: stsfld class [mscorlib]System.Func`2<int32, bool> ConsoleApplication.Program/'<>c'::'<>9__1_0'
 
    IL_002d: stloc.1
    // for (int i = 0; i < 100000000; i++)
    IL_002e: ldc.i4.0
    IL_002f: stloc.2
    // (no C# code)
    IL_0030: br.s IL_0040
    // loop start (head: IL_0040)
        IL_0032: nop
        // Program.DoSomething(i, lambda);
        IL_0033: ldloc.2
        IL_0034: ldloc.1
        IL_0035: call void ConsoleApplication.Program::DoSomething(int32, class [mscorlib]System.Func`2<int32, bool>)
        // (no C# code)
        IL_003a: nop
        IL_003b: nop
        // for (int i = 0; i < 100000000; i++)
        IL_003c: ldloc.2
        IL_003d: ldc.i4.1
        IL_003e: add
        IL_003f: stloc.2
 
        // for (int i = 0; i < 100000000; i++)
        IL_0040: ldloc.2
        IL_0041: ldc.i4 100000000
        IL_0046: clt
        IL_0048: stloc.3
        // (no C# code)
        IL_0049: ldloc.3
        IL_004a: brtrue.s IL_0032
    // end loop

Вариант без выноса
Кликните здесь для просмотра всего текста

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
    // loop start (head: IL_003e)
        IL_0012: nop
        // Program.DoSomething(i, (int x) => x <= 10);
        IL_0013: ldloc.1
        // (no C# code)
        IL_0014: ldsfld class [mscorlib]System.Func`2<int32, bool> ConsoleApplication.Program/'<>c'::'<>9__1_0'
        IL_0019: dup
        IL_001a: brtrue.s IL_0033
 
        IL_001c: pop
        IL_001d: ldsfld class ConsoleApplication.Program/'<>c' ConsoleApplication.Program/'<>c'::'<>9'
        IL_0022: ldftn instance bool ConsoleApplication.Program/'<>c'::'<Main>b__1_0'(int32)
        IL_0028: newobj instance void class [mscorlib]System.Func`2<int32, bool>::.ctor(object, native int)
        IL_002d: dup
        IL_002e: stsfld class [mscorlib]System.Func`2<int32, bool> ConsoleApplication.Program/'<>c'::'<>9__1_0'
 
        IL_0033: call void ConsoleApplication.Program::DoSomething(int32, class [mscorlib]System.Func`2<int32, bool>)
        IL_0038: nop
        IL_0039: nop
        // for (int i = 0; i < 100000000; i++)
        IL_003a: ldloc.1
        IL_003b: ldc.i4.1
        IL_003c: add
        IL_003d: stloc.1
 
        // for (int i = 0; i < 100000000; i++)
        IL_003e: ldloc.1
        IL_003f: ldc.i4 100000000
        IL_0044: clt
        IL_0046: stloc.2
        // (no C# code)
        IL_0047: ldloc.2
        IL_0048: brtrue.s IL_0012
    // end loop
0
 Аватар для Fleder
263 / 224 / 108
Регистрация: 09.12.2015
Сообщений: 652
15.03.2018, 14:42
Цитата Сообщение от kolorotur Посмотреть сообщение
В других случаях или на других компиляторах кэширования может и не быть и делегат будет создаваться каждый раз в цикле.
К другим случаям можно отнести эту засаду?
C#
1
2
3
4
5
6
7
8
9
10
private static bool Predicate(int x) => x <= 10;
 
for(int i = 0; i < N; i++)
{
   ///делегат будет создаваться каждую итерацию
   doSomething(i, Predicate);
 
   ///делегат будет создан один раз
   doSomething(i, x => Predicate(x));
}
1
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
15.03.2018, 14:48
Цитата Сообщение от Fleder Посмотреть сообщение
К другим случаям можно отнести эту засаду?
Да. Аналогично, делегат не будет кэшироваться если в лямбде идет обращение к методу экземпляра:
C#
1
2
3
4
5
// Не static!
bool Predicate(int x) => x <= 10;
 
for (int i = 0; i < N; i++)
   doSomething(i, x => Predicate(x));
3
 Аватар для Fleder
263 / 224 / 108
Регистрация: 09.12.2015
Сообщений: 652
26.03.2018, 19:50
kolorotur, правильно ли я понял, что массив arr переживёт функцию Foo,
в которой был создан?
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
      static Func<double> func = Foo(2048);
 
      public static Func<double> Foo(int length)
      {
         int[] arr = new int[length];
         Random rnd = new Random();
         for(int i = 0; i < arr.Length; ++i)
         {
            arr[i] = rnd.Next();
         }
         Func<double> func = () => arr.Average();
         double avr = func();
         return () => avr;
      }
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
26.03.2018, 20:23
Цитата Сообщение от Fleder Посмотреть сообщение
правильно ли я понял, что массив arr переживёт функцию Foo, в которой был создан?
Оно сильно от компилятора зависит, но в последней версии МСовского — да, массив будет жить до окончания работы программы или до изменения значения func.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
26.03.2018, 20:23
Помогаю со студенческими работами здесь

Выносить -1 или нет?
Вот такой рядок: \sum \frac{n(2+cos\pi n)}{2{n}^{2}-1} Так как косинус равен то 1, то -1... (n от 1 до бесконечности), то выносим...

Необходимо составить лямбду
Значит есть вот такой код: string turn = &quot;&quot;; if (whichTurnIs == 2) turn = &quot;0&quot;; else turn = &quot;X&quot;; listOfButtons.Text = turn;...

Можно ли импликацию выносить за скобки?
Есть выражение : (x -&gt; y) v (x -&gt; z) Если вынести &quot;x -&gt;&quot; за скобку, то получится x -&gt; (y v z). Является ли это составное высказывание...

Обязательно ли выносить запрос в title
Имеется два запроса. Оба в принципе НЧ. Обязательно ли выносить их в title? Или можно обойтись просто парой упоминаний в тексте и...

Можно ли как то выносить XAML ?
У меня есть страница (Page). На ней находиться 2 грида, мне их очень не удобно редактировать в одном файле, я всё время между ними путаюсь....


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru