Разбираем 7 приёмов для регулярных выражений в C#!
Regex удобен для поиска и проверки текста, но сложный шаблон может неожиданно долго обрабатывать почти совпавшую строку. В этой шпоре собраны настройки, которые делают регулярные выражения понятнее и помогают контролировать время выполнения.
➡️ C# Ready | #шпора
Regex удобен для поиска и проверки текста, но сложный шаблон может неожиданно долго обрабатывать почти совпавшую строку. В этой шпоре собраны настройки, которые делают регулярные выражения понятнее и помогают контролировать время выполнения.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9🔥6👍3
Почему MemoryStream.GetBuffer может вернуть лишние байты?
Представим, что API должен отправить короткий двоичный ответ. Мы записали его в MemoryStream, а затем получили внутренний массив:
Кажется, что data должен содержать ровно три байта. Но MemoryStream часто выделяет буфер с запасом. Длина массива отражает вместимость буфера, а не количество записанных данных.
Эти числа можно сравнить напрямую:
Length показывает полезную длину, а Capacity и data.Length могут быть больше. Если отправить весь data в сеть или записать его в файл, к нужным байтам добавится незаполненная часть буфера. В некоторых сценариях там могут оставаться данные после предыдущих операций с этим же массивом.
Когда нужен самостоятельный массив точной длины, используй ToArray:
ToArray копирует только записанные данные. Копия требует дополнительной памяти, зато её длина соответствует содержимому и она не изменится при последующей записи в stream.
Если копирование дорого, можно получить сегмент внутреннего массива вместе с правильными Offset и Count:
Не каждый MemoryStream разрешает доступ к своему буферу, GetBuffer может выбросить исключение, а TryGetBuffer в этом случае вернёт false.
➡️ C# Ready | #совет
Представим, что API должен отправить короткий двоичный ответ. Мы записали его в MemoryStream, а затем получили внутренний массив:
using var stream = new MemoryStream();
stream.Write(new byte[] { 1, 2, 3 });
byte[] data = stream.GetBuffer();
Кажется, что data должен содержать ровно три байта. Но MemoryStream часто выделяет буфер с запасом. Длина массива отражает вместимость буфера, а не количество записанных данных.
Эти числа можно сравнить напрямую:
Console.WriteLine(stream.Length);
Console.WriteLine(stream.Capacity);
Console.WriteLine(data.Length);
Length показывает полезную длину, а Capacity и data.Length могут быть больше. Если отправить весь data в сеть или записать его в файл, к нужным байтам добавится незаполненная часть буфера. В некоторых сценариях там могут оставаться данные после предыдущих операций с этим же массивом.
Когда нужен самостоятельный массив точной длины, используй ToArray:
byte[] payload = stream.ToArray();
await destination.WriteAsync(payload);
ToArray копирует только записанные данные. Копия требует дополнительной памяти, зато её длина соответствует содержимому и она не изменится при последующей записи в stream.
Если копирование дорого, можно получить сегмент внутреннего массива вместе с правильными Offset и Count:
if (stream.TryGetBuffer(out ArraySegment<byte> segment)) {
await destination.WriteAsync(segment.AsMemory());
}Не каждый MemoryStream разрешает доступ к своему буферу, GetBuffer может выбросить исключение, а TryGetBuffer в этом случае вернёт false.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6👍3🔥3
Карта основных возможностей C#!
На картинке язык разложен на крупные ветки: типы, операторы, инструкции, классы, коллекции и LINQ. Цвета помогают быстро увидеть, какие темы относятся к одной группе.
Например, ветка типов ведёт от числовых и ссылочных типов к пользовательским классам, а ветка LINQ объединяет фильтрацию, сортировку, группировку и преобразование данных.
Сохрани, чтобы не потерять!
➡️ C# Ready | #ресурс
На картинке язык разложен на крупные ветки: типы, операторы, инструкции, классы, коллекции и LINQ. Цвета помогают быстро увидеть, какие темы относятся к одной группе.
Например, ветка типов ведёт от числовых и ссылочных типов к пользовательским классам, а ветка LINQ объединяет фильтрацию, сортировку, группировку и преобразование данных.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10👍3🔥2
Знали, как читать обновляемые настройки из singleton-сервиса в ASP.NET Core?
Фоновый сервис обычно живёт всё время работы приложения. Если внедрить в него IOptionsSnapshot<T>, контейнер зависимостей получит scoped-сервис внутри singleton, и такая комбинация нарушает границы времени жизни.
Для долгоживущих сервисов предназначен IOptionsMonitor<T>. Он зарегистрирован как singleton, подходит для внедрения в сервисы любого времени жизни и позволяет получить актуальные настройки через CurrentValue.
Сначала связываем класс настроек с секцией конфигурации:
В singleton сохраняем сам монитор, а не снимок настроек, прочитанный при создании сервиса:
Перед каждой операцией получаем актуальное значение и используем его как единый набор параметров для этой операции:
Если нужно реагировать на изменение сразу, монитор поддерживает уведомления OnChange. Подписку создают один раз на время жизни сервиса и освобождают при остановке, а не создают заново при каждом запросе.
➡️ C# Ready | #совет
Фоновый сервис обычно живёт всё время работы приложения. Если внедрить в него IOptionsSnapshot<T>, контейнер зависимостей получит scoped-сервис внутри singleton, и такая комбинация нарушает границы времени жизни.
Для долгоживущих сервисов предназначен IOptionsMonitor<T>. Он зарегистрирован как singleton, подходит для внедрения в сервисы любого времени жизни и позволяет получить актуальные настройки через CurrentValue.
Сначала связываем класс настроек с секцией конфигурации:
builder.Services.Configure<WorkerOptions>(
builder.Configuration.GetSection("Worker"));
В singleton сохраняем сам монитор, а не снимок настроек, прочитанный при создании сервиса:
private readonly IOptionsMonitor<WorkerOptions> _options;
Перед каждой операцией получаем актуальное значение и используем его как единый набор параметров для этой операции:
WorkerOptions current = _options.CurrentValue;
await RunJobAsync(current.BatchSize, current.Endpoint);
Если нужно реагировать на изменение сразу, монитор поддерживает уведомления OnChange. Подписку создают один раз на время жизни сервиса и освобождают при остановке, а не создают заново при каждом запросе.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4🔥4👍3
Разбираем 7 инструментов System.Text.Json!
С JSON можно работать как с типизированными объектами, так и без заранее описанной модели. Для потоков есть асинхронные методы, а для выборочного чтения и изменения структуры подходят разные представления документа.
В этой шпоре собраны Serialize, Deserialize, SerializeAsync, DeserializeAsync, JsonDocument, TryGetProperty и JsonNode.
➡️ C# Ready | #шпора
С JSON можно работать как с типизированными объектами, так и без заранее описанной модели. Для потоков есть асинхронные методы, а для выборочного чтения и изменения структуры подходят разные представления документа.
В этой шпоре собраны Serialize, Deserialize, SerializeAsync, DeserializeAsync, JsonDocument, TryGetProperty и JsonNode.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12❤5👍4
Claude снова банит пользователей из РФ
Многим начали приходить письма счастья от Anthropic: аккаунт заблокирован, доступ закрыт. Банят за вход из неподдерживаемого региона и оплату через серые схемы.
А в CatCode Claude работает без ограничений.
CatСode - это десктопный агент с топовыми нейросетями на борту всего за 1550 рублей в месяц:
😒 Claude Fable
🤖 GPT-6 Astra
😐 Grok 4.6
и многие другие.
Твой аккаунт точно не забанят: подписка оформлена у международной компании. Работает без VPN, оплата российской картой или СБП, никаких перекупов. Первые задачи бесплатно, просто зарегистрируйся и пробуй.
Оформи пакет нейросетей разом и не бойся банов: catcode.dev
Многим начали приходить письма счастья от Anthropic: аккаунт заблокирован, доступ закрыт. Банят за вход из неподдерживаемого региона и оплату через серые схемы.
А в CatCode Claude работает без ограничений.
CatСode - это десктопный агент с топовыми нейросетями на борту всего за 1550 рублей в месяц:
и многие другие.
Твой аккаунт точно не забанят: подписка оформлена у международной компании. Работает без VPN, оплата российской картой или СБП, никаких перекупов. Первые задачи бесплатно, просто зарегистрируйся и пробуй.
Оформи пакет нейросетей разом и не бойся банов: catcode.dev
Please open Telegram to view this post
VIEW IN TELEGRAM
👎2😁2❤1
Убираем лишние запросы при вводе текста в C#!
При поиске по мере набора символов приложение может отправить запрос на каждый ввод. Добавим небольшую задержку и отмену предыдущей операции, чтобы искать только по последнему значению.
Храним источник отмены текущего поиска и блокировку для его безопасной замены:
Когда приходит новый текст, заменяем источник под блокировкой и отменяем предыдущий поиск:
Блокировка не даёт старой задаче одновременно освободить источник, который новый вызов пытается отменить. Каждый вызов освобождает свой объект сам после завершения.
Ждём короткую паузу, затем выполняем поиск с тем же токеном отмены:
Если за 300 миллисекунд пользователь введёт следующий символ, ожидание или запрос завершится отменой. Проверка перед показом результата не даст старому поиску перезаписать более свежие данные.
В блоке finally очищаем поле только тогда, когда там всё ещё наш источник, и освобождаем его:
Такой debounce сокращает сетевую нагрузку.
➡️ C# Ready | #практика
При поиске по мере набора символов приложение может отправить запрос на каждый ввод. Добавим небольшую задержку и отмену предыдущей операции, чтобы искать только по последнему значению.
Храним источник отмены текущего поиска и блокировку для его безопасной замены:
private readonly object _searchLock = new();
private CancellationTokenSource? _searchCts;
Когда приходит новый текст, заменяем источник под блокировкой и отменяем предыдущий поиск:
var current = new CancellationTokenSource();
lock (_searchLock)
{
var previous = _searchCts;
_searchCts = current;
previous?.Cancel();
}
Блокировка не даёт старой задаче одновременно освободить источник, который новый вызов пытается отменить. Каждый вызов освобождает свой объект сам после завершения.
Ждём короткую паузу, затем выполняем поиск с тем же токеном отмены:
try
{
await Task.Delay(300, current.Token);
var results = await _searchService.FindAsync(query, current.Token);
current.Token.ThrowIfCancellationRequested();
_view.Show(results);
}
catch (OperationCanceledException) when (current.IsCancellationRequested)
{
}
Если за 300 миллисекунд пользователь введёт следующий символ, ожидание или запрос завершится отменой. Проверка перед показом результата не даст старому поиску перезаписать более свежие данные.
В блоке finally очищаем поле только тогда, когда там всё ещё наш источник, и освобождаем его:
finally
{
lock (_searchLock)
{
if (ReferenceEquals(_searchCts, current))
{
_searchCts = null;
}
}
current.Dispose();
}
Такой debounce сокращает сетевую нагрузку.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5👍4❤3
🔥 Middle C# на собеседовании у Senior из европейского highload | 20 октября, 19:00 МСК
Можно знать технологию и всё равно завалить техническое интервью. Часто дело не в знаниях, а в том, как ты отвечаешь и какие детали упускаешь ☝🏻
Александр Моргунов, Senior C# разработчик с 7+ годами опыта в европейском highload, проведёт мок-собеседование в прямом эфире!
Отвечает разработчик-доброволец, вопросов он заранее не знает. После каждого ответа Александр разберёт, что было хорошо, где кандидат потерял баллы и как стоило ответить.
Проверяй себя вместе с кандидатом и узнай, к чему подготовиться до своего собеса.
🚀 Это бесплатно
Эфир проходит в рамках менторской программы ШОРТКАТ для C# разработчиков
Ссылка на эфир в боте 👉 @shortcut_csharp_bot
Реклама.
О рекламодателе.
Можно знать технологию и всё равно завалить техническое интервью. Часто дело не в знаниях, а в том, как ты отвечаешь и какие детали упускаешь ☝🏻
Александр Моргунов, Senior C# разработчик с 7+ годами опыта в европейском highload, проведёт мок-собеседование в прямом эфире!
Отвечает разработчик-доброволец, вопросов он заранее не знает. После каждого ответа Александр разберёт, что было хорошо, где кандидат потерял баллы и как стоило ответить.
Проверяй себя вместе с кандидатом и узнай, к чему подготовиться до своего собеса.
🚀 Это бесплатно
Эфир проходит в рамках менторской программы ШОРТКАТ для C# разработчиков
Ссылка на эфир в боте 👉 @shortcut_csharp_bot
Реклама.
О рекламодателе.
Добавляем Request-Id middleware в ASP.NET Core!
Нужно связывать логи, ошибки и ответы API одним идентификатором запроса. Реализуем middleware, который берёт Request-Id из заголовка или создаёт новый.
В этой задаче:
Такой подход помогает быстрее искать конкретный запрос в логах, трассировке, gateway и клиентских жалобах.
➡️ C# Ready | #задача
Нужно связывать логи, ошибки и ответы API одним идентификатором запроса. Реализуем middleware, который берёт Request-Id из заголовка или создаёт новый.
В этой задаче:
• читаем входящий заголовок
• создаём fallback через Guid
• прокидываем значение в response
• подключаем middleware в pipeline
Такой подход помогает быстрее искать конкретный запрос в логах, трассировке, gateway и клиентских жалобах.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤4🔥3