C# Ready | Unity
10.5K subscribers
1.49K photos
84 videos
745 links
Авторский канал по разработке на C# и Unity.
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!

Cотрудничество: @energy_c

РКН: https://clck.ru/3SBaT3
Download Telegram
Разбираем 7 инструментов System.Text.Json!

С JSON можно работать как с типизированными объектами, так и без заранее описанной модели. Для потоков есть асинхронные методы, а для выборочного чтения и изменения структуры подходят разные представления документа.

В этой шпоре собраны Serialize, Deserialize, SerializeAsync, DeserializeAsync, JsonDocument, TryGetProperty и JsonNode.

➡️ C# Ready | #шпора
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
Please open Telegram to view this post
VIEW IN TELEGRAM
👎2😁2❤1
Убираем лишние запросы при вводе текста в C#!

При поиске по мере набора символов приложение может отправить запрос на каждый ввод. Добавим небольшую задержку и отмену предыдущей операции, чтобы искать только по последнему значению.

Храним источник отмены текущего поиска и блокировку для его безопасной замены:
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 сокращает сетевую нагрузку.

➡️ C# Ready | #практика
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

Реклама.
О рекламодателе.
Добавляем Request-Id middleware в ASP.NET Core!

Нужно связывать логи, ошибки и ответы API одним идентификатором запроса. Реализуем middleware, который берёт Request-Id из заголовка или создаёт новый.

В этой задаче:
• читаем входящий заголовок
• создаём fallback через Guid
• прокидываем значение в response
• подключаем middleware в pipeline


Такой подход помогает быстрее искать конкретный запрос в логах, трассировке, gateway и клиентских жалобах.

➡️ C# Ready | #задача
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤4🔥3
Шпаргалка по регулярным выражениям в .NET!

Regex позволяет находить и заменять текст по шаблону, а готовые методы возвращают результат в удобном для задачи виде. В справочнике собраны короткие примеры вызова и отмечены возможности новых версий .NET.

На картинке есть IsMatch, Match, Matches, Replace, Split, Count, EnumerateMatches, Escape и Unescape. Также показаны RegexOptions и тайм-аут, который ограничивает время поиска при неудачном шаблоне.

➡️ C# Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤3🔥3
Полезный инструмент для IT-айтишников 👇

Если ты разработчик, тестировщик, аналитик или другой специалист из IT и задумываешься о смене работы, присмотрись к этому сервису.

Это проект на базе ИИ, который помогает искать вакансии и упрощает поиск новой работы.

Можно сохранить себе и воспользоваться, когда решишь найти новые карьерные возможности.
Please open Telegram to view this post
VIEW IN TELEGRAM
Зачем передавать TimeProvider вместо прямого вызова DateTimeOffset.UtcNow?

Если код сам читает системные часы, тест зависит от момента запуска. Передай источник времени явно:
public sealed class ExpirationService(TimeProvider clock)
{
    public bool IsExpired(DateTimeOffset expiresAt) =>
        clock.GetUtcNow() >= expiresAt;
}


Сервис теперь не привязан к часам машины. В приложении используй системный провайдер:
services.AddSingleton<TimeProvider>(TimeProvider.System);


В тесте установи фиксированное время через FakeTimeProvider:
var clock = new FakeTimeProvider(
    new DateTimeOffset(2030, 1, 1, 12, 0, 0, TimeSpan.Zero));
var service = new ExpirationService(clock);


Создай дату истечения и сдвинь виртуальные часы до границы:
var expiresAt = clock.GetUtcNow().AddMinutes(5);
clock.Advance(TimeSpan.FromMinutes(5));
Assert.True(service.IsExpired(expiresAt));


Тест выполняется сразу и точно проверяет границу. Добавь пакет для управляемых часов:
dotnet add package Microsoft.Extensions.TimeProvider.Testing


Для управляемых задержек передай тот же провайдер в Task.Delay:
await Task.Delay(TimeSpan.FromMinutes(5), clock, cancellationToken);


В тесте Advance завершит такое ожидание без реальной паузы. Для измерения скорости используй Stopwatch, а не календарные часы.

➡️ C# Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤5🔥4
Обрабатываем список запросов параллельно с ограничением!

Представь, что нужно отправить тысячи записей во внешний API. Последовательный цикл может работать слишком долго, а запуск тысячи Task сразу создаст всплеск соединений и нагрузки. Соберём обработчик, который ограничивает число одновременных операций и умеет штатно отменяться.

Сначала задаём лимит параллелизма и общий токен отмены:
var options = new ParallelOptions
{
    MaxDegreeOfParallelism = 4,
    CancellationToken = cancellationToken
};


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

Передаём каждую запись в асинхронную операцию и не блокируем поток через Wait или Result:
await Parallel.ForEachAsync(records, options, async (record, token) =>
{
    await client.PostAsJsonAsync("/events", record, token);
});


Внутренний token связан с ParallelOptions. Передавай его дальше в HTTP-вызов, чтобы отмена работала не только между элементами, но и во время сетевого ожидания.

Соберём результат ответа и явно обработаем неуспешный HTTP-статус:
await Parallel.ForEachAsync(records, options, async (record, token) =>
{
    using var response = await client.PostAsJsonAsync(
        "/events", record, token);
    response.EnsureSuccessStatusCode();
});


Освобождение ответа важно при массовой обработке. Если один запрос вернул ошибку, исключение выйдет из цикла, поэтому вызывающему коду нужно решить, завершать всю пачку, повторять отдельную запись или собирать ошибки поэлементно.

Запусти обработку внутри обычного try и отличай отмену от сбоя сервера:
try
{
    await Parallel.ForEachAsync(records, options, ProcessAsync);
}


Ожидаемую отмену обработай отдельно от ошибок сервера:
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{
    logger.LogInformation("Обработка отменена");
}


Сетевые ошибки можно записать отдельно или передать вызывающему уровню:
catch (HttpRequestException exception)
{
    logger.LogError(exception, "Не удалось отправить запись");
}


Parallel.ForEachAsync подходит для независимых элементов, когда важен ограниченный параллелизм. Лимит не задаёт частоту запросов в секунду, не сохраняет порядок завершения и сам по себе не реализует повторы.

➡️ C# Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍2🔥2