9818
Авторский канал по разработке на C# и Unity. Ресурсы, гайды, задачи, шпаргалки. Информация ежедневно пополняется! Автор: @energy_it РКН: https://clck.ru/3SBaT3 Реклама на бирже: https://telega.in/c/csharp_ready
Шпаргалка по class, struct и record в C#!
Например, class передаётся по ссылке, struct хранит значение, record class даёт value equality для модели данных, а record struct совмещает value type с удобствами record.
На картинке сравниваются class, struct, record class и record struct. Есть тип хранения, значение по умолчанию, наследование, интерфейсы, immutability, equality, assignment и поведение ToString.
Сохрани, чтобы не потерять!
➡️ C# Ready | #ресурс
Разбираем immutable collections в C#!
Immutable collections помогают передавать данные без риска, что другой участок кода внезапно изменит коллекцию. Это удобно для конфигов, состояния UI, кешей и событий.
В этой шпоре собраны ImmutableArray, ImmutableList, Add, Remove, SetItem, ToImmutableArray и Builder.
➡️ C# Ready | #шпора
Напоминалка по async/await в C#!
Например, await приостанавливает выполнение метода до завершения Task, а Task.WhenAll() помогает дождаться нескольких независимых операций.
На картинке основные идеи async/await: зачем нужна асинхронность, что делают async и await, какие бывают return types, как запускать задачи параллельно и каких ошибок стоит избегать.
Сохрани, чтобы не потерять!
➡️ C# Ready | #ресурс
Шпаргалка по throw и throw ex в C#!
Например, обычный throw внутри catch пробрасывает исходное исключение и сохраняет stack trace. А throw ex создаёт повторный выброс так, что место реальной ошибки становится сложнее найти.
На картинке показана разница между двумя вариантами. Есть сохранение stack trace, потеря исходного контекста, влияние на отладку и короткая таблица с правильным вариантом для catch-блоков.
Сохрани, чтобы не потерять!
➡️ C# Ready | #ресурс
Полезная статья про Avalonia-приложение для Raspberry Pi!
Автор разбирает создание кроссплатформенного приложения на Avalonia и показывает, как связать UI, сборку и доставку проекта через GitHub Actions.
В статье автор показывает:
• как устроить проект на Avalonia под разные платформы
• как подготовить сборку и публикацию через GitHub Actions
• какие нюансы появляются при запуске приложения на Raspberry Pi
Продолжай читать на Habr
Знали, как ограничить количество параллельных async-операций через SemaphoreSlim?
Иногда нужно обработать много элементов, отправить HTTP-запросы, проверить файлы, обновить записи или вызвать внешний API. Кажется логичным запустить всё через Task.WhenAll.
Пример выглядит компактно:
await Task.WhenAll(items.Select(SendAsync));
using var gate = new SemaphoreSlim(5);
await gate.WaitAsync();
try
{
await SendAsync(item);
}
finally
{
gate.Release();
}
var tasks = items.Select(async item =>
{
await gate.WaitAsync();
try { await SendAsync(item); }
finally { gate.Release(); }
});
await Task.WhenAll(tasks);
Собираем автообновление конфига в C#!
Нужно следить за config.json и автоматически перечитывать настройки после изменения файла. Это удобно для сервисов, внутренних тулов и приложений, где часть параметров можно менять без перезапуска.
В этой задаче:
• создаём FileSystemWatcher
• фильтруем события по имени файла
• добавляем короткий debounce
Интересная статья про разработку игры на C# без большого движка!
Автор показывает, как подойти к созданию игры ближе к железу и базовой архитектуре, чтобы лучше понимать цикл обновления, отрисовку и устройство игровых объектов.
В статье автор показывает:
• как думать о game loop и состоянии сцены
• почему полезно понимать основу без готового движка
• какие части игры приходится собирать руками
Продолжай читать на Habr
Разбираем 7 приёмов для кеширования данных!
MemoryCache помогает держать часто используемые данные рядом с приложением. Это удобно для справочников, настроек, результатов дорогих вычислений и ответов внешних сервисов.
➡️ C# Ready | #шпора
Хороший вход в современный C# для начинающих и джунов!
Статья спокойно объясняет, зачем сейчас учить C#, где он применяется и с каких базовых вещей стоит начинать, если хочется двигаться в сторону .NET-разработки.
В статье автор показывает:
• где C# используется в реальных проектах
• какие инструменты нужны на старте
• как подойти к изучению языка без хаоса
Продолжай читать на Habr!
Почему не стоит lock-ать строку или публичный объект?
В C# lock работает по объекту-синхронизатору:
lock (sync)
{
// критическая секция
}
sync используют строку:lock ("cache")
{
UpdateCache();
}"cache":lock ("cache")
{
DoSomethingElse();
}public object Sync = new();
lock, создавая странные зависания.private readonly object _sync = new();
lock (_sync)
{
UpdateCache();
}
Крутая статья о том, как подружить C#, .NET MAUI и Rust в одном приложении!
В этой статье:
• Как подключить Rust-код к MAUI-проекту
• Зачем может понадобиться нативная часть внутри C#-приложения
• Как C# и Rust могут вместе работать с графикой через SkiaSharp
Продолжай читать на Habr!
Делаем простой rate limiter на C#!
Иногда нужно ограничить частоту действий: не давать пользователю слишком часто нажимать кнопку, вызывать команду или отправлять запрос
В этой задаче:
• храним timestamps последних вызовов;
• удаляем старые события;
• проверяем лимит в скользящем окне;
Собираем валидатор пароля на C#!
Нужно проверить пароль и показать пользователю понятные причины отказа? Сделаем небольшой валидатор, где каждое правило отвечает за одну проверку и возвращает конкретную ошибку.
В этой задаче:
• Описываем правила как функции;
• Проверяем длину, цифры, регистр и спецсимволы;
• Собираем все ошибки в один список.
Напоминалка по delegates, events и базовым конструкциям C#!
Например, delegate описывает сигнатуру метода, а event позволяет подписывать обработчики на событие через типизированный делегат.
На картинке пример объявления delegate, регистрация методов, anonymous methods, события, популярные event handler-типы, а также рядом есть краткие блоки по классам, методам, struct, enum, свойствам и циклам.
Сохрани, чтобы не потерять!
➡️ C# Ready | #ресурс
Разбираем LINQ: 7 операторов для повседневной выборки данных!
LINQ помогает писать обработку коллекций компактно и выразительно: фильтровать, преобразовывать, сортировать, группировать и искать элементы без ручных циклов. Эти операторы чаще всего встречаются в прикладном C#-коде, API, сервисах и отчётах.
➡️ C# Ready | #шпора
Парсим простой .env-файл на C#!
В небольших утилитах часто нужно прочитать настройки из файла вида KEY=value: токены, режим запуска, адрес API или путь к директории.
Пример строки:
var line = "APP_ENV=prod";
=:var index = line.IndexOf('=');
var key = line[..index];
var value = line[(index + 1)..];var config = new Dictionary<string, string>();
config[key] = value;
foreach (var raw in File.ReadLines(".env"))
{
var line = raw.Trim();
if (line.Length == 0 || line.StartsWith("#"))
continue;
var index = line.IndexOf('=');
if (index <= 0)
continue;
config[line[..index]] = line[(index + 1)..];
}.env:APP_ENV=prod
PORT=8080
DEBUG=false
Console.WriteLine(config["APP_ENV"]);
Console.WriteLine(config["PORT"]);
prod
8080
.env, но отлично подходит для маленьких внутренних утилит.
Делаем потокобезопасный счётчик через Interlocked!
Иногда нескольким потокам нужно увеличивать одно число. Например, считать обработанные события, успешные запросы или количество ошибок в фоне.
Обычный инкремент выглядит невинно:
_count++;
private int _count;
Interlocked.Increment(ref _count);
Interlocked.Add(ref _count, batchSize);
int current = Interlocked.CompareExchange(ref _count, 0, 0);
private long _bytes;
Interlocked.Add(ref _bytes, size);
Собираем простой in-memory event bus в C#!
Иногда внутри приложения нужно связать части системы без прямых вызовов. Например, заказ создан, а несколько обработчиков должны обновить статистику, отправить уведомление и записать аудит.
Для такой задачи можно собрать маленький event bus на делегатах.
Сначала опишем событие:
public sealed record OrderCreated(
int OrderId,
decimal Amount
);
private readonly Dictionary<Type, List<Func<object, Task>>> _handlers = new();
public void Subscribe<TEvent>(Func<TEvent, Task> handler)
{
var type = typeof(TEvent);
if (!_handlers.ContainsKey(type))
{
_handlers[type] = new();
}
_handlers[type].Add(e => handler((TEvent)e));
}
public async Task Publish<TEvent>(TEvent evt)
{
var type = typeof(TEvent);
if (!_handlers.TryGetValue(type, out var handlers))
{
return;
}
foreach (var handler in handlers)
{
await handler(evt!);
}
}
var bus = new EventBus();
bus.Subscribe<OrderCreated>(e =>
{
Console.WriteLine($"Order {e.OrderId}");
return Task.CompletedTask;
});
await bus.Publish(new OrderCreated(42, 1990m));
Шпаргалка по регулярным выражениям в .NET!
Например, \d помогает искать цифры, \w - символы слова, ^ и $ привязывают шаблон к началу и концу строки, а группы позволяют вытаскивать нужные части совпадения.
На картинке собраны основные элементы Regex в .NET. Есть классы символов, квантификаторы, anchors, группы, inline options, backreferences, замены и методы из System.Text.RegularExpressions.Regex.
Сохрани, чтобы не потерять!
➡️ C# Ready | #ресурс
Шпаргалка по middleware pipeline в ASP.NET Core!
Например, Use добавляет middleware в цепочку обработки, Run завершает pipeline, а Map и MapWhen позволяют разветвлять обработку по пути или условию.
Сохрани, чтобы не потерять!
➡️ C# Ready | #ресурс
Настраиваем JSON-сериализацию через System.Text.Json!
Во многих API нужно отдавать JSON в понятном формате. Часто это camelCase-поля, аккуратные отступы в debug-режиме и отсутствие лишних null-значений.
Для начала подключим пространство имён:
using System.Text.Json;
record User(int Id, string Name, string? Email);
var options = new JsonSerializerOptions();
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
options.WriteIndented = true;
var json = JsonSerializer.Serialize(user, options);
var copy = JsonSerializer.Deserialize<User>(json, options);
Почему ToDictionary может упасть на обычных данных?
Когда нужно быстро превратить список в словарь, часто используют ToDictionary. Это удобно, пока ключи уникальные.
Например, есть список пользователей и нужно быстро искать их по email.
var byEmail = users.ToDictionary(u => u.Email);
var byEmail = users
.GroupBy(u => u.Email)
.ToDictionary(g => g.Key, g => g.First());
var byEmail = users
.GroupBy(u => u.Email)
.ToDictionary(g => g.Key, g => g.Last());
var byEmail = users.ToLookup(u => u.Email);
var duplicates = users
.GroupBy(u => u.Email)
.Where(g => g.Count() > 1);
var byEmail = users
.GroupBy(u => u.Email, StringComparer.OrdinalIgnoreCase)
.ToDictionary(g => g.Key, g => g.First(), StringComparer.OrdinalIgnoreCase);
var email = user.Email.Trim().ToLowerInvariant();
Пишем парсер query string на C#!
Нужно разобрать строку вида ?page=2&tag=cs&tag=api и получить структуру, где повторяющиеся ключи не перетирают друг друга.
В этой задаче:
• убираем лишний вопросительный знак
• делим строку на пары
• декодируем ключи и значения
Проверяем срок действия TLS-сертификата!
Нужно быстро понять, когда у сайта закончится HTTPS-сертификат? Соберём простую проверку через openssl: подключимся к серверу, достанем notAfter и посчитаем, сколько дней осталось до истечения.
В этой задаче:
• Получаем сертификат через openssl s_client;
• Достаём дату окончания через openssl x509;
• Считаем разницу и проверяем порог.
7 дней бесплатного обучения frontend-разработке!
Получи востребованные навыки:
1. Генерация сайтов через Giga, DeepSeek, ChatGPT
2. Вёрстка страниц по макету на HTML + CSS
3. Оживление сайта анимацией элементов
4. Публикация сайта
5 Оформление портфолио
6. Поиск заказов
7. Лайфхаки по карьере
И советы по доработке проекта от опытных разработчиков.
Присоединяйся
👆
Разберём HttpClient: 7 возможностей для аккуратной работы с API!
HttpClient часто используют для интеграций, микросервисов и внешних HTTP-запросов. Чтобы код не превращался в ручную сборку строк, заголовков и JSON, стоит знать базовые возможности клиента.
В этой шпоре:
• базовый адрес через BaseAddress;
• общие заголовки;
• GET-запросы;
Полезная статья про Avalonia и реализацию MVVM на C# по шагам!
В этой статье:
• Что такое Avalonia и почему она интересна для кроссплатформенного desktop
• Как разделить интерфейс и бизнес-логику через MVVM
• Как постепенно собрать пример приложения с View, ViewModel, binding и данными
Продолжай читать на Habr!
Делаем простой троттлинг действий в C#!
Иногда событие срабатывает слишком часто: ввод в поиске, resize окна, клики по кнопке или обновление фильтра. Чтобы не запускать тяжёлую операцию каждый раз, можно ограничить частоту выполнения.
Для начала создадим время последнего запуска:
DateTimeOffset lastRun = DateTimeOffset.MinValue;
TimeSpan interval = TimeSpan.FromSeconds(2);
bool CanRun()
{
return DateTimeOffset.UtcNow - lastRun >= interval;
}
if (CanRun())
{
lastRun = DateTimeOffset.UtcNow;
Console.WriteLine("search");
}
sealed class Throttler
{
private DateTimeOffset _lastRun = DateTimeOffset.MinValue;
private readonly TimeSpan _interval;
public Throttler(TimeSpan interval)
{
_interval = interval;
}
public bool TryRun(Action action)
{
var now = DateTimeOffset.UtcNow;
if (now - _lastRun < _interval)
{
return false;
}
_lastRun = now;
action();
return true;
}
}
var throttler = new Throttler(TimeSpan.FromSeconds(2));
throttler.TryRun(() => Console.WriteLine("send request"));
throttler.TryRun(() => Console.WriteLine("send request"));
Полезная статья про создание Telegram-бота на C# с нуля!
В этой статье:
• Как зарегистрировать бота через BotFather и получить токен
• Как создать C#-проект и подключить Telegram.Bot
• Как принимать сообщения и постепенно собрать основу рабочего бота
Продолжай читать на Habr!