День семидесятый. #ЗаметкиНаПолях
For Или Foreach в C#
Многие программисты до сих пор путаются, когда использовать цикл
Внутри цикла
Дело в том,
Кроме того, в общем случае
Подводя итог, когда вам нужна простота чтения кода, используйте
Источник: https://www.c-sharpcorner.com/article/for-vs-foreach-in-c-sharp/
For Или Foreach в C#
Многие программисты до сих пор путаются, когда использовать цикл
for
, а когда foreach
. Рассмотрим перебор элементов коллекции в обоих циклах.List<Employee> employees = GetEmployeesList();Цикл for для списка будет выглядеть примерно так:
for (int i = 0; i < employees.Count; i++)Заметьте, что вы можете напрямую обращаться к элементам списка по индексу.
{
Console.WriteLine(employees[i].Age);
}
Внутри цикла
foreach
вы можете напрямую обращаться к каждому элементу: foreach(Employee emp in Employees)Заметьте, что цикл
{
Console.WriteLine(emp.Age);
}
foreach
создаёт копию коллекции, по которой вы проходите. Это означает, что, если вы хотите выполнить операцию присваивания на элементе коллекции, вы не сможете этого сделать:int[] numbers = { 1, 2, 3, 4, 5, 6 };Этот код приводит к ошибке
foreach (int item in numbers)
{
item++;
}
CS1656: Cannot assign to 'item' because it is a 'foreach iteration variable' (Невозможно выполнить присваивание переменной item, поскольку это ‘переменная итерации цикла foreach’)
.Дело в том,
item
здесь не ссылается на элемент массива, это просто временная переменная, и вы не можете присваивать ей значения.Кроме того, в общем случае
foreach
требует больше времени и дополнительную память, по сравнению с for
, поскольку использует методы GetEnumarator()
и Next()
интерфейса IEnumarable
.Подводя итог, когда вам нужна простота чтения кода, используйте
foreach
, когда требуется доступ к элементам внутри цикла, а также критична производительность, используйте for
. Источник: https://www.c-sharpcorner.com/article/for-vs-foreach-in-c-sharp/
День семьдесят первый. #CSharp8
Новые функции в C# 8.
2. Обнуляемый Ссылочный Тип
В C#8 можно объявлять обнуляемый контекст с помощью аннотации
Для необнуляемых ссылочных типов компилятор использует анализ потока, чтобы убедиться, что локальные переменные инициализированы не-
Обнуляемые ссылочные типы не проверяются на присваивание
Источник: https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8
Новые функции в C# 8.
2. Обнуляемый Ссылочный Тип
В C#8 можно объявлять обнуляемый контекст с помощью аннотации
#nullable
. Внутри него любые переменные ссылочного типа считаются необнуляемыми. Если вы хотите присвоить ссылочному типу null
, нужно явно объявить обнуляемый тип переменной с помощью <тип>?
.Для необнуляемых ссылочных типов компилятор использует анализ потока, чтобы убедиться, что локальные переменные инициализированы не-
null
значением. Все поля должны быть инициализированы в конструкторе. Компилятор выдаёт предупреждение, если переменная не объявляется вызовом любого из доступных конструкторов или инициализатором.Обнуляемые ссылочные типы не проверяются на присваивание
null
, однако компилятор использует анализ потока, чтобы убедиться, что переменная обнуляемого типа не содержит null
, прежде чем к ней обращается код или она присваивается переменной необнуляемого типа.Источник: https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8
День семьдесят второй. #CSharp8
Новые функции в C# 8.
3. Продвинутое Сопоставление с Шаблоном
Сопоставление выражения с шаблоном предоставляет инструменты для сравнения по форме связанных, но разных типов данных. В C# 7.0 был представлен синтаксис шаблонов типа и шаблонов констант, используя выражения
C# 8.0 расширяет эту функциональность, так что вы можете использовать больше шаблонных выражений в разнообразных местах вашего кода. Используйте эти функции, когда ваши данные и функционал разделены, когда ваши алгоритмы не зависят от типа объекта во время выполнения. В дополнение к новым шаблонам в новых местах, в C# 8.0 вводятся рекурсивные шаблоны. Результат любого шаблона выражения – это выражение. Рекурсивный шаблон – это просто шаблон выражения, применённый к результату другого шаблона выражения.
Преимущества
Рекурсивное сопоставление с шаблоном помогает вам разбить структуры данных на компоненты и использовать их в очень удобном и компактном синтаксисе. Несмотря на то, что сопоставление с шаблоном эквивалентно последовательности выражений if-then, оно помогает вам писать код в стиле функционального программирования.
Недостатки
В сложных выражениях синтаксис может быть хитрым и сложным для понимания.
В следующем примере шаблон выражения используется для сопоставления структуры с шаблоном:
Шаблон свойства позволяет вам сопоставить свойства исследуемого объекта. В следующем примере метод рассчитывает налог с продаж в зависимости от штата (свойство
Некоторые типы включают метод
Источники:
- https://www.c-sharpcorner.com/article/c-sharp-8-features/
- https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8
Новые функции в C# 8.
3. Продвинутое Сопоставление с Шаблоном
Сопоставление выражения с шаблоном предоставляет инструменты для сравнения по форме связанных, но разных типов данных. В C# 7.0 был представлен синтаксис шаблонов типа и шаблонов констант, используя выражения
is
и switch
. C# 8.0 расширяет эту функциональность, так что вы можете использовать больше шаблонных выражений в разнообразных местах вашего кода. Используйте эти функции, когда ваши данные и функционал разделены, когда ваши алгоритмы не зависят от типа объекта во время выполнения. В дополнение к новым шаблонам в новых местах, в C# 8.0 вводятся рекурсивные шаблоны. Результат любого шаблона выражения – это выражение. Рекурсивный шаблон – это просто шаблон выражения, применённый к результату другого шаблона выражения.
Преимущества
Рекурсивное сопоставление с шаблоном помогает вам разбить структуры данных на компоненты и использовать их в очень удобном и компактном синтаксисе. Несмотря на то, что сопоставление с шаблоном эквивалентно последовательности выражений if-then, оно помогает вам писать код в стиле функционального программирования.
Недостатки
В сложных выражениях синтаксис может быть хитрым и сложным для понимания.
В следующем примере шаблон выражения используется для сопоставления структуры с шаблоном:
var point = new 3DPoint(1, 2, 3); //x=1, y=2, z=3Шаблоны свойств
if (point is 3DPoint(1, var myY, _))
{
// Этот код будет выполнен, только если point.X == 1
// myY – это новая переменная,
// которая будет доступна только в этом блоке
// Третий член объекта игнорируется спецсимволом _
}
Шаблон свойства позволяет вам сопоставить свойства исследуемого объекта. В следующем примере метод рассчитывает налог с продаж в зависимости от штата (свойство
State
извлекается из передаваемого объекта типа Address
). Расчёт этого налога не является ответственностью класса Address
, поскольку он может изменяться гораздо чаще, чем структура адреса:public static decimal ComputeSalesTax(Address location, decimal salePrice) =>Позиционные шаблоны
location switch
{
{ State: "WA" } => salePrice * 0.06M,
{ State: "MN" } => salePrice * 0.075M,
{ State: "MI" } => salePrice * 0.05M,
// ...
_ => 0M
};
Некоторые типы включают метод
Deconstruct
, который деконструирует свойства в отдельные переменные. Когда доступен метод Deconstruct
, вы можете использовать позиционные шаблоны для сопоставления свойств с шаблоном. Рассмотрим следующий класс точки с координатами X
и Y
:public class PointТакже у нас имеется перечисление, представляющее собой позицию точки в системе координат: неизвестна, в центре, в первом квадратне, во втором квадранте, …, на оси координат:
{
public int X { get; }
public int Y { get; }
public Point(int x, int y) => (X, Y) = (x, y);
public void Deconstruct(out int x, out int y) =>
(x, y) = (X, Y);
}
public enum QuadrantСледующий метод использует позиционный шаблон для извлечения значений
{
Unknown,
Origin,
One,
Two,
Three,
Four,
OnBorder
}
x
и y
, а также использует условие when
для определения квадранта:static Quadrant GetQuadrant(Point point) => point switchШаблон пустого кортежа
{
(0, 0) => Quadrant.Origin,
var (x, y) when x > 0 && y > 0 => Quadrant.One,
var (x, y) when x < 0 && y > 0 => Quadrant.Two,
var (x, y) when x < 0 && y < 0 => Quadrant.Three,
var (x, y) when x > 0 && y < 0 => Quadrant.Four,
var (_, _) => Quadrant.OnBorder,
_ => Quadrant.Unknown
};
(_, _)
соответствует случаю, когда либо x
, либо y
равно 0, но не оба. Выражение switch
должно либо возвращать значение, либо выбрасывать исключение. Если ни один из вариантов не находит соответствия, выражение switch
выбрасывает исключение. Компилятор выдаст предупреждение, если вы не укажете все возможные варианты в выражении switch
.Источники:
- https://www.c-sharpcorner.com/article/c-sharp-8-features/
- https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8
День семьдесят третий. #CSharp8
Новые функции в C# 8.
4. Асинхронные потоки
Начиная с C# 8.0 вы можете создавать и потреблять потоки асинхронно. Метод, возвращающий асинхронный поток, имеет три свойства:
1. Объявляется с модификатором
2. Возвращает
3. Содержит выражения
Потребитель асинхронного потока должен добавить ключевое слово
Следующий код генерирует последовательность от 0 до 19 с ожиданием 100ms между генерациями каждого числа. Затем можно перебрать последовательность, используя выражение
Заметьте, что для выполнения этого кода требуется установить SDK .NET Core 3.0 и использовать его в качестве Target framework в свойствах проекта. А чтобы он появился в этом списке, возможно, потребуется отметить флажок “Use previews of the .NET Core SDK” в Tools > Options > Projects and Solutions > .NET Core и перезагрузить Visual Studio.
Преимущества
Асинхронные потоки предоставляют замечательную возможность представить асинхронные источники данных, которые могут контролироваться потребителем. Например, при загрузке данных из сети, мы хотели бы создать асинхронную коллекцию, которая возвращает данные по частям, как только те становятся доступными.
Источники:
- https://www.c-sharpcorner.com/article/c-sharp-8-features/
- https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8
Новые функции в C# 8.
4. Асинхронные потоки
Начиная с C# 8.0 вы можете создавать и потреблять потоки асинхронно. Метод, возвращающий асинхронный поток, имеет три свойства:
1. Объявляется с модификатором
async
.2. Возвращает
IAsyncEnumerable<T>
.3. Содержит выражения
yield return
, чтобы возвращать последующие элементы из асинхронного потока.Потребитель асинхронного потока должен добавить ключевое слово
await
перед ключевым словом foreach
при переборе элементов потока. Добавление ключевого слова await
требует, чтобы метод, который перечисляет элементы асинхронного потока, был объявлен с модификатором async
и возвращал тип, разрешенный для асинхронного метода. Обычно это означает возврат типа Task
или Task<TResult>
, а также может быть ValueTask
или ValueTask<TResult>
. Метод может как потреблять, так и производить асинхронный поток, что значит, что он будет возвращать IAsyncEnumerable<T>
. Следующий код генерирует последовательность от 0 до 19 с ожиданием 100ms между генерациями каждого числа. Затем можно перебрать последовательность, используя выражение
await foreach
:using System;
using System.Threading.Tasks;
using System.Collections.Generic;
static async Task Main(string[] args)
{
await foreach (var number in GenerateSequence())
{
Console.WriteLine(number);
}
}
public static async System.Collections.Generic.IAsyncEnumerable<int> GenerateSequence()
{
for (int i = 0; i < 20; i++)
{
await Task.Delay(100);
yield return i;
}
}
Заметьте, что для выполнения этого кода требуется установить SDK .NET Core 3.0 и использовать его в качестве Target framework в свойствах проекта. А чтобы он появился в этом списке, возможно, потребуется отметить флажок “Use previews of the .NET Core SDK” в Tools > Options > Projects and Solutions > .NET Core и перезагрузить Visual Studio.
Преимущества
Асинхронные потоки предоставляют замечательную возможность представить асинхронные источники данных, которые могут контролироваться потребителем. Например, при загрузке данных из сети, мы хотели бы создать асинхронную коллекцию, которая возвращает данные по частям, как только те становятся доступными.
Источники:
- https://www.c-sharpcorner.com/article/c-sharp-8-features/
- https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8
День семьдесят четвёртый. #CSharp8
Новые функции в C# 8.
5. Индексы и диапазоны
Диапазоны и индексы предоставляют краткий синтаксис указания поддиапазонов элементов массива или типов
Вы можете указать индекс с конца, используя оператор
Вы можете указать диапазон с помощью оператора
Рассмотрим следующий массив строк, обозначенный индексами с начала и с конца:
Вы можете получить последнее слово с помощью индекса
Заметьте, что для использования диапазонов требуется установить SDK .NET Core 3.0 и использовать его в качестве Target framework в свойствах проекта. А чтобы он появился в этом списке, возможно, потребуется отметить флажок “Use previews of the .NET Core SDK” в Tools > Options > Projects and Solutions > .NET Core и перезагрузить Visual Studio.
Источник: https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8
Новые функции в C# 8.
5. Индексы и диапазоны
Диапазоны и индексы предоставляют краткий синтаксис указания поддиапазонов элементов массива или типов
Span<T>
или ReadOnlySpan<T>
.Вы можете указать индекс с конца, используя оператор
^
. Выражение array[2]
означает "2й элемент с начала". Теперь можно использовать array[^2]
, что означает "2й элемент с конца". Индекс ^0 означает "конец", то есть индекс, следующий за последним элементом.Вы можете указать диапазон с помощью оператора
..
. Например, 0..^0
обозначает весь диапазон массива: 0
с начала до, но не включая, 0
с конца. Любой из операндов оператора может быть как индексом "с начала", так и "с конца". Более того, любой из операндов может быть опущен. По умолчанию 0
– начальный индекс, ^0
– конечный индекс.Рассмотрим следующий массив строк, обозначенный индексами с начала и с конца:
var words = new string[]Индекс каждого элемента усиливает концепцию "с начала" и "с конца", а диапазоны исключают конец диапазона. "Старт" массива – это первый элемент, а "конец" массива находится за последним элементом.
{
// с начала с конца
"The", // 0 ^9
"quick", // 1 ^8
"brown", // 2 ^7
"fox", // 3 ^6
"jumped", // 4 ^5
"over", // 5 ^4
"the", // 6 ^3
"lazy", // 7 ^2
"dog" // 8 ^1
};
Вы можете получить последнее слово с помощью индекса
^1
:Console.WriteLine($"The last word is {words[^1]}");Следующий код создаёт поддиапазон со словами "quick", "brown" и "fox". Он включает элементы с
// выведет "dog"
words[1]
до words[3]
. Элемент words[4]
не входит в диапазон.var quickBrownFox = words[1..4];Следующий код создаёт поддиапазон со словами "lazy" и "dog". Он включает элементы
words[^2]
и words[^1]
. Конечный индекс words[^0]
не включается:var lazyDog = words[^2..^0];Следующие примеры создают диапазоны, открытые с начала, с конца и с обоих концов:
var allWords = words[..]; // содержит все словаВы также можете объявлять диапазоны как переменные, которые потом могут использоваться внутри квадратных скобок:
var firstPhrase = words[..4]; // слова от "The" до "fox"
var lastPhrase = words[6..]; // слова "the", "lazy" и "dog"
Range phrase = 1..4;Заметьте, что, если вы укажете неверный диапазон, где начальное значение больше конечного, то будет выброшено исключение времени выполнения
var text = words[phrase];
System.OverflowException
, например:var invalidRange = words[5..2];При этом компилятор не выдаёт ошибок или предупреждений во время компиляции, даже если вы явно указываете большее начальное значение (по крайней мере в нынешней версии).
var invalidEnd = words[6..^4];
Заметьте, что для использования диапазонов требуется установить SDK .NET Core 3.0 и использовать его в качестве Target framework в свойствах проекта. А чтобы он появился в этом списке, возможно, потребуется отметить флажок “Use previews of the .NET Core SDK” в Tools > Options > Projects and Solutions > .NET Core и перезагрузить Visual Studio.
Источник: https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8
День семьдесят пятый. #CSharp8
Новые функции в C# 8.
6. Декларации using
Декларация
Источник: https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8
Новые функции в C# 8.
6. Декларации using
Декларация
using
– это определение переменной, которому предшествует ключевое слово using
. Оно сообщает компилятору, что определяемая переменная должна быть высвобождена в конце текущего блока кода: static void WriteLinesToFile(IEnumerable<string> lines)В предыдущем примере переменная file освобождается перед тем, как в коде встречается закрывающая скобка метода. Это конец блока, в котором она определена. Предыдущий пример аналогичен использованию блока using:
{
using var file = new System.IO.StreamWriter("WriteLines2.txt");
foreach (string line in lines)
{
file.WriteLine(line);
}
// переменная file высвобождается здесь
}
using (var file = new System.IO.StreamWriter("WriteLines2.txt"))В обоих случаях компилятор вызывает метод
{
// …
}
Dispose()
. Компилятор выбросит ошибку, если выражение в операторе using
не является освобождаемым.Источник: https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8
День семьдесят шестой. #CSharp8
Новые функции в C# 8.
7. Статические локальные функции
Вы теперь можете добавлять модификатор
Рассмотрим следующий код. Локальная функция
Новые функции в C# 8.
7. Статические локальные функции
Вы теперь можете добавлять модификатор
static
к локальным функциям, чтобы убедиться, что локальная функция не включает (не ссылается) на переменные из обрамляющего её блока кода. Если это произойдёт, будет выброшено исключение CS8421 "A static local function can't contain a reference to <variable>." ("Статическая локальная функция не может ссылаться на <имя переменной>.")
.Рассмотрим следующий код. Локальная функция
LocalFunction
ссылается на переменную y
, объявленную в обрамляющем её коде (методе M
). Поэтому LocalFunction
не может быть объявлена статической:int M()Следующий код содержит статическую локальную функцию. Она может быть объявлена статической, поскольку она не содержит никаких ссылок на переменные из обрамляющего её кода:
{
int y;
LocalFunction();
return y;
void LocalFunction() => y = 0;
}
int M()Источник: https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8
{
int y = 5;
int x = 7;
return Add(x, y);
static int Add(int left, int right) => left + right;
}
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. Изменяйте значения переменных без изменения кода
Сталкивались ли вы при отладке с тем, что значение переменной не то, которое вы ожидали? Либо вы просто хотели бы изменить его, чтобы посмотреть, как поведёт себя код? Вы можете легко это сделать при отладке, просто изменив значение переменной в памяти, используя один из следующих методов, который лучше для вас подходит (см. ниже).