This media is not supported in your browser
VIEW IN TELEGRAM
День семьдесят седьмой. #TipsAndTricks
Отладка в Visual Studio. Малоизвестные трюки
1. Задать Следующее Выражение
Многие знают о контекстном меню
1. Наведите на линию кода, куда вы хотите переместить жёлтую стрелку.
2. Зажмите
3. Нажмите на иконку, и жёлтая стрелка переместится на эту строку.
4. Это будет выражением, которое выполнится на следующем шаге или при продолжении отладки (
Отладка в Visual Studio. Малоизвестные трюки
1. Задать Следующее Выражение
Многие знают о контекстном меню
Set Next Statement
(Ctrl+Shift+F10
) – задать следующее выражение, которое перемещает жёлтую стрелку на нужную строку кода. Вы также можете перетащить её вверх или вниз с помощью мыши. Но начиная с Visual Studio 2017 версии 15.3 есть другой способ. 1. Наведите на линию кода, куда вы хотите переместить жёлтую стрелку.
2. Зажмите
CTRL
и заметьте, что зелёная иконка Run to Click
(Выполнить до этого места) меняется на жёлтую Set Next Statement
.3. Нажмите на иконку, и жёлтая стрелка переместится на эту строку.
4. Это будет выражением, которое выполнится на следующем шаге или при продолжении отладки (
F5
).День семьдесят восьмой. #TipsAndTricks
Отладка в Visual Studio. Малоизвестные трюки
2. Прерывание при смене значения
У вас бывали ситуации при отладке, когда вы смотрите на значение свойства в одной точке прерывания, а при переходе к другой точке, значение внезапно меняется? Можно поставить прерывание в мутаторе (
1. В точке останова с интересующим экземпляром, щёлкните правой кнопкой на объект и выберите "
2. Перейдите в мутатор нужного вам свойства и добавьте условие прерывания "
3. Продолжите отладку (
4. В стеке вызовов (
Замечание: Object ID ссылается на адрес в памяти, поэтому он изменяется в каждой сессии отладки. Поэтому вам придётся пересоздавать object ID каждый раз. Обработчик ($1) не изменится, поэтому точку останова можно оставить как есть.
Отладка в Visual Studio. Малоизвестные трюки
2. Прерывание при смене значения
У вас бывали ситуации при отладке, когда вы смотрите на значение свойства в одной точке прерывания, а при переходе к другой точке, значение внезапно меняется? Можно поставить прерывание в мутаторе (
set
) свойства класса, но тогда оно будет возникать для всех экземпляров этого типа. А вам нужен только один проблемный экземпляр. Вы можете использовать Object ID
и условные прерывания, чтобы сузить проблемную область.1. В точке останова с интересующим экземпляром, щёлкните правой кнопкой на объект и выберите "
Make Object ID
". Это даст вам обработчик объекта по ссылке "$1
".2. Перейдите в мутатор нужного вам свойства и добавьте условие прерывания "
this == $1
".3. Продолжите отладку (
F5
), и теперь она остановится при изменении свойства этого экземпляра.4. В стеке вызовов (
Call Stack
) нажмите дважды на предпоследний пункт. Это перенесёт вас в строку кода, изменяющую значение свойства выбранного вами экземпляра.Замечание: Object ID ссылается на адрес в памяти, поэтому он изменяется в каждой сессии отладки. Поэтому вам придётся пересоздавать object ID каждый раз. Обработчик ($1) не изменится, поэтому точку останова можно оставить как есть.
👍3
День семьдесят девятый. #TipsAndTricks
Отладка в Visual Studio. Малоизвестные трюки
3. Переприкрепление К Процессу
Иногда при разработке приложения вы не можете просто начать его отладку через
Когда вы откроете диалог Прикрепить к Процессу (
После успешного прикрепления к процессу появится возможность повторного прикрепления к процессу -
Отладчик сначала попробует найти тот же процесс, сопоставив ID и имя процесса. Если он его не найдёт, то поиск продолжится по имени. Если будет найдет один процесс, отладчик прикрепится к нему. Если процессов будет найдено несколько, отладчик покажет диалог
Поддерживается возможность переприкрепления к нескольким процессам. Например, если вы использовали диалог
Источник: https://blogs.msdn.microsoft.com/devops/2017/03/07/reattach-to-process-in-visual-studio-2017/
Отладка в Visual Studio. Малоизвестные трюки
3. Переприкрепление К Процессу
Иногда при разработке приложения вы не можете просто начать его отладку через
F5
. Тогда вы можете выбрать пункт меню Прикрепить к Процессу, чтобы отладить его. Зачастую, чтобы таким образом производить отладку, вам нужно осуществлять прикрепление к процессу несколько раз. В Visual Studio 2017 введена новая опция Reattach to Process
(Shift+Alt+P
), которая позволяет вам начать отладку вашего приложения в один клик, без необходимости проходить через весь диалог прикрепления к процессу каждый раз. Вам всё равно придётся вручную прикрепиться к процессу в первый раз после открытия Visual Studio. Однако в этот диалог добавлен новый поисковый фильтр, чтобы быстрее находить нужное приложение.Когда вы откроете диалог Прикрепить к Процессу (
Attach to Process
) - Ctrl+Alt+P
, фильтр поиска появится в верхней части списка доступных процессов. Введите имя процесса, к которому вы хотите прикрепиться, и выберите его из списка. Фильтр "прилипчивый", то есть значение фильтра сохранится, когда вы снова откроете этот диалог.После успешного прикрепления к процессу появится возможность повторного прикрепления к процессу -
Reattach to Process
(Shift+Alt+P
).Отладчик сначала попробует найти тот же процесс, сопоставив ID и имя процесса. Если он его не найдёт, то поиск продолжится по имени. Если будет найдет один процесс, отладчик прикрепится к нему. Если процессов будет найдено несколько, отладчик покажет диалог
Attach to Process
для выбора нужного.Поддерживается возможность переприкрепления к нескольким процессам. Например, если вы использовали диалог
Attach to Process
для отладки пяти разных процессов в одной сессии отладки, а затем вызвали Reattach to Process
, отладчик снова прикрепится ко всем доступным процессам. Для тех, которые не будут найдены, будет выброшено сообщение об ошибке, что прикрепиться к процессу не удалось и почему. Затем откроется диалог Attach to Process
, чтобы вы смогли вручную выбрать недостающие процессы или нажать отмена и продолжить только с найденными процессами.Источник: https://blogs.msdn.microsoft.com/devops/2017/03/07/reattach-to-process-in-visual-studio-2017/
This media is not supported in your browser
VIEW IN TELEGRAM
День восьмидесятый. #TipsAndTricks
Отладка в Visual Studio. Малоизвестные трюки
4. Отображение Потоков в Коде
Отладка многопотокового приложения редко бывает простой, но, когда вы можете посмотреть, на какой строке кода находится каждый поток, становится гораздо лучше.
1. На панели отладчика нажмите "Show Threads in Source" ("Показать Потоки в Коде").
2. В полоске с точками останова появится иконка рядом с каждой строкой кода, на которой остановился хотя бы один поток.
3. Наведите курсор на иконку потока, чтобы увидеть идентификаторы и имена всех потоков, которые остановились на этой строке.
4. Щёлкните правой кнопкой на потоке, чтобы увидеть все доступные действия, вроде остановки потока или выбора активного потока.
Заметьте: Эта функциональность сказывается на производительности и снижает скорость отладки. Рекомендуется отключать её, когда вы её не используете.
Отладка в Visual Studio. Малоизвестные трюки
4. Отображение Потоков в Коде
Отладка многопотокового приложения редко бывает простой, но, когда вы можете посмотреть, на какой строке кода находится каждый поток, становится гораздо лучше.
1. На панели отладчика нажмите "Show Threads in Source" ("Показать Потоки в Коде").
2. В полоске с точками останова появится иконка рядом с каждой строкой кода, на которой остановился хотя бы один поток.
3. Наведите курсор на иконку потока, чтобы увидеть идентификаторы и имена всех потоков, которые остановились на этой строке.
4. Щёлкните правой кнопкой на потоке, чтобы увидеть все доступные действия, вроде остановки потока или выбора активного потока.
Заметьте: Эта функциональность сказывается на производительности и снижает скорость отладки. Рекомендуется отключать её, когда вы её не используете.
This media is not supported in your browser
VIEW IN TELEGRAM
День восемьдесят первый. #TipsAndTricks
Отладка в Visual Studio. Малоизвестные трюки
4. Проход по шагам внутри одного потока
Как часто при отладке многопотокового кода вы останавливаетесь на точке, делаете шаг и внезапно останавливаетесь в другом потоке? Это происходит из-за того, что точка останова установлена и последовательно достигается разными потоками. По умолчанию отладчик будет останавливаться на ней каждый раз, когда её достигает. При выполнении шага все потоки возобновляются, и один из них достигает точки останова перед тем, как завершается шаг в текущем потоке. В следующий раз попробуйте следующее:
1. Деактивируйте или удалите точку останова, на которой останавливается другой поток.
2. Продолжите выполнение - Continue (F5)
3. Проследите как ваш изначальный шаг в первом потоке завершается и теперь он в текущем контексте отладки.
5. Поскольку ваши точки останова удалены или неактивны, вы можете продолжить отладку по шагам в единственном потоке без прерываний.
Отладка в Visual Studio. Малоизвестные трюки
4. Проход по шагам внутри одного потока
Как часто при отладке многопотокового кода вы останавливаетесь на точке, делаете шаг и внезапно останавливаетесь в другом потоке? Это происходит из-за того, что точка останова установлена и последовательно достигается разными потоками. По умолчанию отладчик будет останавливаться на ней каждый раз, когда её достигает. При выполнении шага все потоки возобновляются, и один из них достигает точки останова перед тем, как завершается шаг в текущем потоке. В следующий раз попробуйте следующее:
1. Деактивируйте или удалите точку останова, на которой останавливается другой поток.
2. Продолжите выполнение - Continue (F5)
3. Проследите как ваш изначальный шаг в первом потоке завершается и теперь он в текущем контексте отладки.
5. Поскольку ваши точки останова удалены или неактивны, вы можете продолжить отладку по шагам в единственном потоке без прерываний.
День восемьдесят второй. #Оффтоп
Понимаю, что, наверное, начинают надоедать однообразные посты о трюках, советах и новинках ещё не вышедшего С# 8. Но ничего не могу поделать. Застрял на нескольких главах Рихтера про сборщик мусора и домены приложения. Интересно, но довольно занудно и длинно написано. Кроме того, сборщик мусора - обширная и достаточно сложная система, что не позволяет хоть как-нибудь сжать 60-страничное содержание главы и уместить его даже в несколько постов. Да и такие сильно технические детали, если и могут быть интересны, то скорее чисто теоретически. Уверен, что 99% разработчиков за всю карьеру не придётся ни разу каким-либо образом вмешиваться в механизм сборщика мусора. Хотя, возможно, я ошибаюсь.
В общем, просто хотел обозначить, что процесс обучения и подготовки к экзамену продолжается, посты из серии "Заметки на полях" ещё будут.
А пока могу порекомендовать серию лекций на YouTube об алгоритмах сортировки от CodeBlog. Сегодня в 20:00 первая лекция про пузырьковую сортировку https://www.youtube.com/watch?v=LxliVjZo1Nc
Понимаю, что, наверное, начинают надоедать однообразные посты о трюках, советах и новинках ещё не вышедшего С# 8. Но ничего не могу поделать. Застрял на нескольких главах Рихтера про сборщик мусора и домены приложения. Интересно, но довольно занудно и длинно написано. Кроме того, сборщик мусора - обширная и достаточно сложная система, что не позволяет хоть как-нибудь сжать 60-страничное содержание главы и уместить его даже в несколько постов. Да и такие сильно технические детали, если и могут быть интересны, то скорее чисто теоретически. Уверен, что 99% разработчиков за всю карьеру не придётся ни разу каким-либо образом вмешиваться в механизм сборщика мусора. Хотя, возможно, я ошибаюсь.
В общем, просто хотел обозначить, что процесс обучения и подготовки к экзамену продолжается, посты из серии "Заметки на полях" ещё будут.
А пока могу порекомендовать серию лекций на YouTube об алгоритмах сортировки от CodeBlog. Сегодня в 20:00 первая лекция про пузырьковую сортировку https://www.youtube.com/watch?v=LxliVjZo1Nc
This media is not supported in your browser
VIEW IN TELEGRAM
День восемьдесят третий. #TipsAndTricks
Отладка в Visual Studio. Малоизвестные трюки
6. Определение Значения Функции без Побочных Эффектов
У вас бывали случаи, когда вы вводили выражение в окно Watch или Immediate, чтобы оценить их значение, а потом вам приходилось сталкиваться с побочными эффектами, потому что статус приложения изменился? Обычно это случается, если выражение вызывает функцию, которая приводит к побочным эффектам (изменяет статус приложения). Это может быть не страшно, если вы об этом знаете, а что, если нет? Вот как оценить значение выражения в C# без риска испортить остальную программу.
1. Добавьте "
2. Это приведёт к интерпретации выражения в отдельной «песочнице», не затрагивая основное приложение.
3. Если выражение не может быть интерпретировано таким образом, вы получите сообщение об ошибке.
4. Если вы уверены, что хотите оценить выражение всё равно, уберите модификатор "
Отладка в Visual Studio. Малоизвестные трюки
6. Определение Значения Функции без Побочных Эффектов
У вас бывали случаи, когда вы вводили выражение в окно Watch или Immediate, чтобы оценить их значение, а потом вам приходилось сталкиваться с побочными эффектами, потому что статус приложения изменился? Обычно это случается, если выражение вызывает функцию, которая приводит к побочным эффектам (изменяет статус приложения). Это может быть не страшно, если вы об этом знаете, а что, если нет? Вот как оценить значение выражения в C# без риска испортить остальную программу.
1. Добавьте "
, nse
" (означает “No Side Effects” – Без Побочных Эффектов) после каждого выражения.2. Это приведёт к интерпретации выражения в отдельной «песочнице», не затрагивая основное приложение.
3. Если выражение не может быть интерпретировано таким образом, вы получите сообщение об ошибке.
4. Если вы уверены, что хотите оценить выражение всё равно, уберите модификатор "
, nse
" и попробуйте снова.This media is not supported in your browser
VIEW IN TELEGRAM
День восемьдесят четвёртый. #TipsAndTricks
Отладка в Visual Studio. Малоизвестные трюки
7. Стеки вызовов для всех потоков
Когда есть много потоков, есть и много стеков вызовов. Вам может потребоваться проверить их все, чтобы понять состояние приложения. Вы всегда можете посмотреть на визуальное отображение стека вызовов каждого потока, используя окно Параллельные Стеки (Parallel Stacks) -
1. Откройте окно Command (
2. Введите "
3. Вы также можете использовать популярную команду из WinDBG – "
4. Теперь все потоки со своими стеками вызовов выведены в окне Command.
Отладка в Visual Studio. Малоизвестные трюки
7. Стеки вызовов для всех потоков
Когда есть много потоков, есть и много стеков вызовов. Вам может потребоваться проверить их все, чтобы понять состояние приложения. Вы всегда можете посмотреть на визуальное отображение стека вызовов каждого потока, используя окно Параллельные Стеки (Parallel Stacks) -
Debug > Windows > Parallel Stacks
. Также в окне Command можно посмотреть текстовое представление стека вызовов каждого потока, которое можно скопировать и вставить.1. Откройте окно Command (
View > Other Windows > Command Window
).2. Введите "
Debug.ListCallStacks –AllThreads
"3. Вы также можете использовать популярную команду из WinDBG – "
~*k
"4. Теперь все потоки со своими стеками вызовов выведены в окне Command.
This media is not supported in your browser
VIEW IN TELEGRAM
День восемьдесят пятый. #TipsAndTricks
Отладка в Visual Studio. Малоизвестные трюки
8. Наблюдайте за значениями переменных в рекурсивных вызовах функции
Случалось ли вам отлаживать рекурсивные функции, используя многочисленные вызовы
1. Откройте окно Parallel Watch (
2. Нажмите “
3. По мере того, как вы проходите по рекурсивным вызовам, вы увидите, как они добавляются в новые строки окна.
Отладка в Visual Studio. Малоизвестные трюки
8. Наблюдайте за значениями переменных в рекурсивных вызовах функции
Случалось ли вам отлаживать рекурсивные функции, используя многочисленные вызовы
Debug.WriteLine()
? Иногда бывает сложно решить в голове, как отработает рекурсивная функция. Помочь в этом может окно Parallel Watch, в котором можно отследить изменения переменных в рекурсивном вызове.1. Откройте окно Parallel Watch (
Debug > Windows > Parallel Watch
).2. Нажмите “
<Add Watch>
” и введите имя нужной переменной. 3. По мере того, как вы проходите по рекурсивным вызовам, вы увидите, как они добавляются в новые строки окна.
This media is not supported in your browser
VIEW IN TELEGRAM
День восемьдесят шестой. #TipsAndTricks
Отладка в Visual Studio. Малоизвестные трюки
9. Установка точки прерывания на функции без поиска её в коде
Иногда бывает нужно отладить код функции, нахождение которой в коде может вызвать трудности. Один из быстрых способов установки точки прерывания в отладчике без поиска файла и строки кода состоит в установке Точки Прерывания на Функции.
1. Нажмите
2. Введите имя функции, на которой вы хотите установить точку прерывания. Нажмите OK.
3. Начните отладку, и заметьте, что отладчик останавливается на этой магической точке прерывания в файле кода, который вам не пришлось искать вручную.
Отладка в Visual Studio. Малоизвестные трюки
9. Установка точки прерывания на функции без поиска её в коде
Иногда бывает нужно отладить код функции, нахождение которой в коде может вызвать трудности. Один из быстрых способов установки точки прерывания в отладчике без поиска файла и строки кода состоит в установке Точки Прерывания на Функции.
1. Нажмите
Ctrl+B
, либо выберите в меню Debug > New Breakpoint > Function Breakpoint
.2. Введите имя функции, на которой вы хотите установить точку прерывания. Нажмите OK.
3. Начните отладку, и заметьте, что отладчик останавливается на этой магической точке прерывания в файле кода, который вам не пришлось искать вручную.
День восемьдесят седьмой. #ЗаметкиНаПолях
Выражение yield return. Начало
Выражение
Небольшой пример, не имеющий особого смысла, но полезный для отладки и понимания работы
Yield return против обычных циклов
Вот другой пример. Здесь обычный цикл, возвращающий список:
Выполнение этого кода по шагам:
1. Вызывается
2. Выполняется весь метод и создаётся список.
3. Цикл
4. В результате числа от 1 до 5 выводятся в консоль.
Аналогичный метод с помощью
1. Вызывается
2. Тип возвращаемого значения этого метода
3. В каждой итерации цикла
4. В результате в консоли выводятся числа от 1 до 5.
Источники:
- https://docs.microsoft.com/ru-ru/dotnet/csharp/language-reference/keywords/yield
- https://www.kenneth-truyers.net/2016/05/12/yield-return-in-c/
Продолжение следует…
Выражение yield return. Начало
Выражение
yield return
, вероятно, одна из наименее известных функций в C#. Несмотря на то, что большинство разработчиков о нём слышали, это выражение часто понимается неправильно. Использование ключевого слова yield
в методе означает, что этот метод, оператор или акцессор get
является итератором. Использование yield
исключает необходимость применения явного дополнительного класса для хранения перечисления. Примеры использования:yield return <expression>; // возвращает каждый элемент по одномуМетод-итератор используется путем применения оператора
yield break; // завершает итерацию
foreach
или запроса LINQ. Каждая итерация цикла foreach
вызывает метод-итератор. При достижении в методе-итераторе оператора yield return
возвращается <expression>
и сохраняется текущее расположение в коде. При следующем вызове метода-итератора выполнение возобновляется с этого места.Небольшой пример, не имеющий особого смысла, но полезный для отладки и понимания работы
yield return
:IEnumerable GetNumbers() {Вызовем его:
yield return 1;
yield return 2;
yield return 3;
}
foreach(var number in GetNumbers())Когда вы пройдёте его по шагам в отладке, вы увидите, что текущая строка выполнения прыгает между циклом
Console.WriteLine(number);
foreach
и выражениями yield return
. То есть каждая итерация цикла вызывает метод-итератор GetNumbers
до очередного выражения yield return
. Значение возвращается вызывающему коду, а позиция в методе-итераторе сохраняется. Выполнение возобновляется с этой позиции при следующем вызове метода-итератора. Это продолжается, пока не будут вызваны все выражения yield return
, либо не встретится yield break
.Yield return против обычных циклов
Вот другой пример. Здесь обычный цикл, возвращающий список:
IEnumerable<int> GenerateWithoutYield();
{
var i = 0;
var list = new List<int>();
while (i<5)
list.Add(++i);
return list;
}
foreach(var number in GenerateWithoutYield())
Console.WriteLine(number)
Выполнение этого кода по шагам:
1. Вызывается
GenerateWithoutYield
.2. Выполняется весь метод и создаётся список.
3. Цикл
foreach
проходит по всем значениям списка.4. В результате числа от 1 до 5 выводятся в консоль.
Аналогичный метод с помощью
yield return
:IEnumerable<int> GenerateWithYield()На первый взгляд этот метод тоже возвращает список из 5 чисел. Но из-за выражения
{
var i = 0;
while (i<5)
yield return ++i;
}
foreach(var number in GenerateWithYield())
Console.WriteLine(number);
yield
код выполняется совершенно по-другому. Метод вообще не возвращает списка. Он создаёт итератор с обещанием вернуть 5 чисел. Несмотря на то, что результат тот же, есть некоторые нюансы выполнения:1. Вызывается
GenerateWithYield
.2. Тип возвращаемого значения этого метода
IEnumerable
, но это не список, а обещание вернуть последовательность чисел при запросе. Точнее создаётся итератор, позволяющий выполнить это обещание.3. В каждой итерации цикла
foreach
вызывается метод-итератор. При достижении выражения yield return
возвращается значение, а текущее положение запоминается. Выполнение продолжается с этого места при следующем вызове метода-итератора.4. В результате в консоли выводятся числа от 1 до 5.
Источники:
- https://docs.microsoft.com/ru-ru/dotnet/csharp/language-reference/keywords/yield
- https://www.kenneth-truyers.net/2016/05/12/yield-return-in-c/
Продолжение следует…
День восемьдесят восьмой. #TipsAndTricks
Отладка в Visual Studio. Малоизвестные трюки
10. Изменяйте значения переменных без изменения кода
Сталкивались ли вы при отладке с тем, что значение переменной не то, которое вы ожидали? Либо вы просто хотели бы изменить его, чтобы посмотреть, как поведёт себя код? Вы можете легко это сделать при отладке, просто изменив значение переменной в памяти, используя один из следующих методов, который лучше для вас подходит (см. ниже).
Отладка в Visual Studio. Малоизвестные трюки
10. Изменяйте значения переменных без изменения кода
Сталкивались ли вы при отладке с тем, что значение переменной не то, которое вы ожидали? Либо вы просто хотели бы изменить его, чтобы посмотреть, как поведёт себя код? Вы можете легко это сделать при отладке, просто изменив значение переменной в памяти, используя один из следующих методов, который лучше для вас подходит (см. ниже).
This media is not supported in your browser
VIEW IN TELEGRAM
1. В подсказках данных (DataTips)
Наведите курсор мыши на переменную, чтобы получить всплывающую подсказку со значением переменной. Кликните один раз на значение в подсказке, либо кликните правой кнопкой и выберите "Edit value" ("Изменить значение") из выпадающего меню. Появится курсор редактирования, и вы сможете ввести новое значение переменной.
Наведите курсор мыши на переменную, чтобы получить всплывающую подсказку со значением переменной. Кликните один раз на значение в подсказке, либо кликните правой кнопкой и выберите "Edit value" ("Изменить значение") из выпадающего меню. Появится курсор редактирования, и вы сможете ввести новое значение переменной.
This media is not supported in your browser
VIEW IN TELEGRAM
2. В окнах Autos, Locals или Watch
Кликните дважды на значении в списке, либо кликните правой кнопкой и выберите "Edit value" ("Изменить значение") из выпадающего меню. Значение станет редактируемым, и вы сможете ввести новое значение переменной.
Кликните дважды на значении в списке, либо кликните правой кнопкой и выберите "Edit value" ("Изменить значение") из выпадающего меню. Значение станет редактируемым, и вы сможете ввести новое значение переменной.
This media is not supported in your browser
VIEW IN TELEGRAM
3. В окне Immediate
Вы можете использовать кодовый синтаксис для задания переменной нового значения. Например, вы можете ввести “
Вы можете использовать кодовый синтаксис для задания переменной нового значения. Например, вы можете ввести “
x = 12;
”, что изменит значение переменной x
в памяти на число 12
. Этот метод наиболее подходит в тех случаях, когда вам нужно провести какие-нибудь манипуляции со значением перед тем, как присвоить его переменной.День восемьдесят девятый. #ЗаметкиНаПолях
Выражение yield return. Примеры использования
1. Кастомные итерации
Допустим, у нас есть список чисел. Мы хотим отобразить все числа, которые больше определённого числа. Обычно нам пришлось бы:
- создать временный список,
- в цикле пройти по исходному списку, сохраняя во временный список подходящие значения,
- пройти по временному списку, чтобы использовать полученные значения.
Мы можем избежать лишней работы, используя
2. Итерации с сохранением состояния
Метод-итератор, содержащий
3. Асинхронные потоки
В C# 8 появилась возможность создавать асинхронные потоки, которые были описаны в этом посте: https://t.iss.one/NetDeveloperDiary/88
Источники:
- https://docs.microsoft.com/ru-ru/dotnet/csharp/language-reference/keywords/yield
- https://www.kenneth-truyers.net/2016/05/12/yield-return-in-c/
Продолжение следует…
Выражение yield return. Примеры использования
1. Кастомные итерации
Допустим, у нас есть список чисел. Мы хотим отобразить все числа, которые больше определённого числа. Обычно нам пришлось бы:
- создать временный список,
- в цикле пройти по исходному списку, сохраняя во временный список подходящие значения,
- пройти по временному списку, чтобы использовать полученные значения.
Мы можем избежать лишней работы, используя
yield return
:IEnumerable<int> GetNumbersGreaterThan3(List<int> numbers)Здесь выполнение кода совершенно другое. Исходный список перебирается всего один раз, и только нужные значения выдаются методом-итератором вызывающему коду (в этом случае циклу
{
foreach(var nr in numbers)
{
if(nr > 3)
yield return nr;
}
}
foreach(var nr in GetNumbersGreaterThan3(new List<int> {1,2,3,4,5})
Console.WriteLine(nr);
foreach
).2. Итерации с сохранением состояния
Метод-итератор, содержащий
yield return
, сохраняет не только позицию после выдачи очередного значения, но и своё состояние:IEnumerable<int> Totals(List<int> numbers)Этот код вернёт значения
{
var total = 0;
foreach(var number in numbers)
{
total += number;
yield return total;
}
}
foreach(var total in Totals(new List<int> {1,2,3,4,5})
Console.WriteLine(total);
1,3,6,10,15
. Поскольку состояние сохраняется, переменная total
будет сохранять значения между итерациями, тем самым подсчитывая промежуточную сумму чисел списка.3. Асинхронные потоки
В C# 8 появилась возможность создавать асинхронные потоки, которые были описаны в этом посте: https://t.iss.one/NetDeveloperDiary/88
Источники:
- https://docs.microsoft.com/ru-ru/dotnet/csharp/language-reference/keywords/yield
- https://www.kenneth-truyers.net/2016/05/12/yield-return-in-c/
Продолжение следует…
День девяностый. #TipsAndTricks
Отладка в Visual Studio. Малоизвестные трюки
11. Отмечайте потоки и выполняйте их все до выбранного места
При отладке многопоточного кода, вероятно, вам придётся делать точки останова и идти оттуда по шагам, что приведёт к тому, что программа возобновит выполнение других потоков. Иногда для поиска ошибки может быть проще остановить все потоки в одном месте, чтобы проверить состояние программы в это время. Есть простой способ сделать это, отметив потоки и вызвав команду Run Flagged Threads to Cursor (Выполнить Отмеченные Потоки до Курсора).
1. Определите интересующие вас потоки. Вы можете использовать пункт меню Show Threads in Source (Показать Потоки в Коде), окна Parallel Debugging (Параллельная Отладка) или окно Threads (Потоки).
2. Отметьте флажком интересующие вас потоки.
3. Щёлкните правой кнопкой на строке кода, в которой вы хотите исследовать состояние приложения.
4. Из контекстного меню выберите Run Flagged Threads to Cursor (Выполнить Отмеченные Потоки до Курсора).
Замечание: Когда включена опция Show Threads in Source (Показать Потоки в Коде) или видимы любые окна, относящиеся к потокам, это может серьёзно сказаться на производительности вашей сессии отладки. Рекомендуется использовать эти инструменты только когда вы действительно используете их для отладки.
Отладка в Visual Studio. Малоизвестные трюки
11. Отмечайте потоки и выполняйте их все до выбранного места
При отладке многопоточного кода, вероятно, вам придётся делать точки останова и идти оттуда по шагам, что приведёт к тому, что программа возобновит выполнение других потоков. Иногда для поиска ошибки может быть проще остановить все потоки в одном месте, чтобы проверить состояние программы в это время. Есть простой способ сделать это, отметив потоки и вызвав команду Run Flagged Threads to Cursor (Выполнить Отмеченные Потоки до Курсора).
1. Определите интересующие вас потоки. Вы можете использовать пункт меню Show Threads in Source (Показать Потоки в Коде), окна Parallel Debugging (Параллельная Отладка) или окно Threads (Потоки).
2. Отметьте флажком интересующие вас потоки.
3. Щёлкните правой кнопкой на строке кода, в которой вы хотите исследовать состояние приложения.
4. Из контекстного меню выберите Run Flagged Threads to Cursor (Выполнить Отмеченные Потоки до Курсора).
Замечание: Когда включена опция Show Threads in Source (Показать Потоки в Коде) или видимы любые окна, относящиеся к потокам, это может серьёзно сказаться на производительности вашей сессии отладки. Рекомендуется использовать эти инструменты только когда вы действительно используете их для отладки.
День девяносто первый. #ЗаметкиНаПолях
Выражение yield return. Особенности работы
1. Множественные итерации
Побочным эффектом выражения
1. Когда выполняется строка
2. Этот итератор передаётся в метод
3. Внутри метода
4. Однако все объекты, созданные в методе
5. Когда мы возвращаемся во внешний код, у нас остаётся только ссылка на итератор. Вызывая метод
Поскольку это неочевидное поведение, инструменты вроде Resharper предупреждают вас о множественных итерациях.
2. Отложенное выполнение
Все примеры использования
1. Выбрать все 1000 продуктов
2. Посчитать цену всех 1000 продуктов
3. Выстроить все продукты по возрастанию цены
4. Перевести все цены в доллары
5. Выбрать 5 продуктов с самой высокой ценой
Используя отложенное выполнение, код:
1. Выбирает 10 продуктов
2. Вычисляет цену 10 продуктов
3. Выстраивает из по возрастанию цены
4. Отбирает первые 5 и переводит их цены в доллары
Несмотря на то, что это выдуманный пример, он чётко показывает, как отложенное выполнение может сильно повысить эффективность. Хотя, заметьте, что пример с отложенным выполнением может делать не то, что вы хотите. В примере выше из всех продуктов отбираются не 10 с наиболее высокой ценой, а 10 первых попавшихся. Поэтому нужно быть внимательным в порядке вызова методов LINQ.
Источники:
- https://docs.microsoft.com/ru-ru/dotnet/csharp/language-reference/keywords/yield
- https://www.kenneth-truyers.net/2016/05/12/yield-return-in-c/
Выражение yield return. Особенности работы
1. Множественные итерации
Побочным эффектом выражения
yield return
является то, что множественные вызовы приводят к множественным итерациям:static void Main(string[] args)Попробуйте догадаться, что будет выведено в консоль? Несмотря на то, что интуиция подсказывает результат
{
var invoices = GetInvoices();
DoubleAmounts(invoices);
Console.WriteLine(invoices.First().Amount);
}
class Invoice { public double Amount { get; set; } }
static IEnumerable<Invoice> GetInvoices()
{
for (var i = 1; i < 11; i++)
yield return new Invoice { Amount = i * 10 };
}
static void DoubleAmounts(IEnumerable<Invoice> invoices)
{
foreach (var invoice in invoices)
invoice.Amount = invoice.Amount * 2;
}
20
, выведено будет 10
:1. Когда выполняется строка
var invoices = GetInvoices();
мы не получаем список счетов (Invoice
), мы получаем итератор, создающий объекты Invoice
.2. Этот итератор передаётся в метод
DoubleAmounts
.3. Внутри метода
DoubleAmounts
итератор используется для создания объектов Invoice
и удвоения суммы счёта (свойство Amount
) каждого объекта.4. Однако все объекты, созданные в методе
DoubleAmounts
, выбрасываются, поскольку на них нет ссылок из внешнего кода.5. Когда мы возвращаемся во внешний код, у нас остаётся только ссылка на итератор. Вызывая метод
First
, мы снова просим создать объект Invoice. Это новый объект, поэтому в результате его свойство Amount
будет иметь значение 10
.Поскольку это неочевидное поведение, инструменты вроде Resharper предупреждают вас о множественных итерациях.
2. Отложенное выполнение
Все примеры использования
yield return
имеют общее свойство. Код выполняется только тогда, когда это необходимо. Механизм паузы/возобновления в методе-итераторе делает это возможным. Используя отложенное выполнение, мы можем делать методы проще, иногда быстрее, а иногда и в принципе делать возможным то, что было невозможно ранее. Например, можно сделать бесконечный генератор чисел и выбирать из него только нужное количество. Весь модуль LINQ в C# построен вокруг отложенного исполнения. Вот как оно повышает эффективность кода:var dollarPrices = FetchProducts().Take(10)Допустим, у нас 1000 продуктов. Без отложенного выполнения, методу бы пришлось:
.Select(p => p.CalculatePrice())
.OrderBy(price => price)
.Take(5)
.Select(price => ConvertTo$(price));
1. Выбрать все 1000 продуктов
2. Посчитать цену всех 1000 продуктов
3. Выстроить все продукты по возрастанию цены
4. Перевести все цены в доллары
5. Выбрать 5 продуктов с самой высокой ценой
Используя отложенное выполнение, код:
1. Выбирает 10 продуктов
2. Вычисляет цену 10 продуктов
3. Выстраивает из по возрастанию цены
4. Отбирает первые 5 и переводит их цены в доллары
Несмотря на то, что это выдуманный пример, он чётко показывает, как отложенное выполнение может сильно повысить эффективность. Хотя, заметьте, что пример с отложенным выполнением может делать не то, что вы хотите. В примере выше из всех продуктов отбираются не 10 с наиболее высокой ценой, а 10 первых попавшихся. Поэтому нужно быть внимательным в порядке вызова методов LINQ.
Источники:
- https://docs.microsoft.com/ru-ru/dotnet/csharp/language-reference/keywords/yield
- https://www.kenneth-truyers.net/2016/05/12/yield-return-in-c/