9818
Авторский канал по разработке на C# и Unity. Ресурсы, гайды, задачи, шпаргалки. Информация ежедневно пополняется! Автор: @energy_it РКН: https://clck.ru/3SBaT3 Реклама на бирже: https://telega.in/c/csharp_ready
👩💻 URL и адреса в C# — без ручного парсинга и лишних ошибок!В этой шпаргалке — как безопасно создавать Uri, валидировать адреса, кодировать параметры, доставать части URL и строить относительные ссылки без хрупкой работы со строками
➡️ C# Ready | #шпора
Span<T> - работаем с памятью без лишних аллокаций!
Иногда нужно обработать часть массива, строки или буфера без создания новых объектов в памяти.
Раньше для этого часто приходилось копировать данные в новый массив:
int[] numbers = { 1, 2, 3, 4, 5, 6 };
int[] slice = numbers.Skip(2).Take(3).ToArray();
foreach (var n in slice)
Console.WriteLine(n);ToArray() создает новый массив в памяти. Если таких операций много, появляются лишние аллокации и нагрузка на GC.Span<T>, чтобы работать с частью данных без копирования:int[] numbers = { 1, 2, 3, 4, 5, 6 };
Span<int> slice = numbers.AsSpan(2, 3);
foreach (var n in slice)
Console.WriteLine(n);Span<T> создает представление на участок памяти, а не новый массив. То есть ты работаешь с нужной частью данных без лишних выделений памяти.
❤️ Нашёл полезный материал на Microsoft Learn — пошаговый гайд по добавлению QR-кодов для 2FA в Blazor WebAssembly с Identity!
В этой статье:• Как подключить генерацию QR-кодов для приложений-аутентификаторов.• Как настроить TOTP-аутентификацию и связать её с Identity.• Как обновить страницы и логику входа для работы с 2FA и recovery codes
🔊 Продолжай читать на Microsoft Learn!
📂 Шпаргалка по HTTPS — как устанавливается защищённое соединение!
На картинке — схема: TCP handshake, затем TLS/SSL с проверкой сертификата, обменом ключами (асимметричное шифрование) и созданием session key, после чего идёт передача данных уже по симметричному шифрованию.
Сохрани, чтобы быстро вспоминать этапы HTTPS без погружения в документацию
➡️ C# Ready | #ресурс
☕️ Нашёл полезный материал на Microsoft Learn — быстрый старт по созданию WPF-приложения!
В этой статье:• Как создать проект WPF в Visual Studio и запустить первое окно.
• Как добавлять элементы интерфейса и обрабатывать базовые события.
• Как собрать приложение и подготовить его к запуску/публикации.
🔊 Продолжай читать на Microsoft Learn!
📱 LateUpdate: камера без дрожания в движении!
Если камера обновляется не в том цикле, картинка начинает дергаться, и даже хорошая физика выглядит плохо.
В этом гайде:
• Показываем, почему появляется дрожание при разных циклах обновления;
• Переносим камеру в LateUpdate, чтобы она читала финальную позицию цели;
• Добавляем SmoothDamp и Interpolate для мягкого и стабильного слежения.
Почему using и await using дают разный результат?
На вид разница только в одном слове. Но поведение разное.using вызывает синхронный Dispose. await using вызывает DisposeAsync и ждет его завершения. Если у ресурса есть реальная асинхронная очистка, например сетевой flush или закрытие канала, это критично.
Если случайно оставить обычный using, код может выглядеть корректно, но фактическое освобождение пройдет не так, как ты ожидаешь.
await using var conn = new SqlConnection(cs);
await conn.OpenAsync();
IAsyncDisposable используй await using, чтобы очистка завершалась предсказуемо.
👩💻 PDF-счёт за секунды без рутины
QuestPDF создаёт аккуратный счёт из ваших данных, избавляя команду от редакторов и копипаста ручного труда.
Что важно знать
• Меняет стиль легко
• Работает на любом компьютере
• Создаёт файл мгновенно
Как убрать «лес» вложенных `if` из метода?
Часто вся валидация и проверки прав зашиваются внутрь одной большой конструкции, и тело метода уезжает вправо на пол-экрана:
void ProcessOrder(Order order)
{
if (order != null)
{
if (order.IsPaid)
{
if (!order.IsCancelled)
{
Ship(order);
}
}
}
}
void ProcessOrder(Order order)
{
if (order is null) return;
if (!order.IsPaid) return;
if (order.IsCancelled) return;
Ship(order);
}
☕️ Нашёл полезный материал на Хабре — конкретные NuGet-пакеты для повседневной разработки!
В этой статье:• Какие пакеты реально экономят время в типовых задачах.
• Где пакет уместен в проде, а где лучше остаться на стандартном API.
• Как оценивать риски новой зависимости перед подключением.
🔊 Продолжай читать на Habr!
Бесплатные нейронки, изменившие жизнь:
🤬 Обход GPT, Deepseek, Gemini, Sora - Читать гайд
🎁 Флирт бот, влюбит в тебя любую только он - Узнать название
💪 Помогает накачаться знает ВСЁ о питании - Узнать название
🎁 Решает домашку, по фотке твоего задания - Узнать название
💸 Генерирует идеи для заработка, без бюджета - Узнать название
📉 Мониторит сайты и уведомляет о падении цен - Узнать название
📹 Делает тиктоки на сотни тысяч просмотров - Узнать название
Зачем в библиотечном async-коде часто ставят `ConfigureAwait(false)`?
Потому что await по умолчанию пытается “вернуться” в исходный контекст выполнения. В UI это может быть полезно. Но в библиотеке это обычно лишнее и иногда даже вредное.
Частая картина: внутри библиотеки есть await, а дальше никакого UI нет. Но метод всё равно тащит контекст вызывающего кода:
await http.GetStringAsync("/data");await http.GetStringAsync("/data").ConfigureAwait(false);await ты обновляешь UI, ConfigureAwait(false) может быть неуместен. Это другое правило.
📂 Напоминалка по HTTP и сетевым протоколам!
Например, HTTP/1.1 использует постоянные соединения, HTTP/2 умеет мультиплексировать запросы в одном TCP-канале, а HTTP/3 работает поверх QUIC и UDP.
На картинке — наглядная эволюция HTTP от первых версий до современных стандартов.
Сохрани, чтобы не забыть!
➡️ C# Ready | #ресурс
Возможно, у кого-то есть старый аккаунт Google Play Разработчика (до 2023 года).
Есть возможность хорошо заработать на этом.
Закрытые за неактив аккаунты тоже принимаются(помогу бесплатно восстановить)
По любым вопросам в ЛС @Ilya01s.
Как узнать, какой аргумент пришёл null, без ручных строк?
Обычно в проверках хочется написать “что именно было null”, но если делать это строками, они быстро устаревают после рефакторинга. В итоге кто-то переименовал переменную, а сообщение об ошибке осталось старым.
В C# можно сделать так, чтобы имя выражения подставлялось автоматически — через CallerArgumentExpression. Смотри на параметр:
[CallerArgumentExpression("value")] string? expr = nullNotNull(user);
user окажется null, исключение будет ArgumentNullException("user") — без магических строк и без копипасты. NotNull(cache[key]);
CallerArgumentExpression — это “бесплатная диагностика”. Меньше ручных сообщений, лучше ошибки, и после переименований всё остаётся корректным автоматически.
☕️ Ultimate Awesome — огромная подборка с ресурсам!
Этот репозиторий настоящий мета-каталог по самым разным технологиям. Внутри собраны тысячи подборок с библиотеками, инструментами, статьями и гайдами по программированию. Отдельные разделы посвящены языкам C# и C++, где можно найти библиотеки, фреймворки, проекты и обучающие ресурсы.
Оставляю ссылочку: GitHub 📱
Почему Any() читается лучше, чем Count() > 0?
Когда в коде нужно просто проверить, есть ли элементы, запись через Count() > 0 выглядит чуть тяжелее, чем нужно. По ней как будто мы реально хотим что-то посчитать, хотя на деле нас интересует только сам факт: пусто или нет.
Гораздо проще читается такой вариант:
if (users.Any())
{
SendPromo(users);
}
Any() сразу передаёт намерение: “есть ли хоть кто-то”. Без лишнего шума и без ощущения, что мы решаем другую задачу.
👩💻 Понятные пути без боя с слэшамиВ этой шпаргалке — ключевые приёмы работы с Path: как собирать корректные пути через Combine, вытаскивать имя файла и расширение, менять их на лету и получать аккуратные абсолютные пути, которые одинаково уверенно живут и под Windows, и под Linux.
➡️ C# Ready | #шпора
Как перестать собирать строки через `+` в цикле?
Когда мы складываем строки в цикле, кажется, что всё просто: text += ....
Но строки в C# неизменяемые — каждая такая операция создаёт новую строку. В итоге на больших списках получаем лишние аллокации, нагрузку на GC и падение скорости.
Если нужно просто склеить коллекцию значений — используем string.Join:
var text = string.Join(", ", names);Append — берём StringBuilder и собираем строку без постоянного пересоздания:var sb = new StringBuilder();
sb.AppendLine(...);
var text = sb.ToString();
string.Join, для сложной сборки — StringBuilder. Меньше мусора в памяти, меньше нагрузки на GC, и код выглядит как правило, а не ручная сборка строки.
Храним секреты в Windows Credential Manager!
Пароли и токены часто кладут прямо в appsettings.json — небезопасно, да и коммитить стыдно:
string dbPassword = "P@ssw0rd"; // лежит в файле — легко утечёт
using CredentialManagement; // nuget: CredentialManagement
// создаём источник
using var cred = new Credential
{
Target = "MyApp:DbPassword", // уникальный ключ
Password = "S3cureP@ss!", // сам секрет
PersistanceType = PersistanceType.LocalComputer
};
cred.Save(); // безопасно сохранили
using var read = new Credential { Target = "MyApp:DbPassword" };
if (read.Load())
Console.WriteLine("Секрет: " + read.Password);
else
Console.WriteLine("Запись не найдена");
📂 Напоминалка по HTTP vs HTTPS!
Например, HTTP передаёт данные в открытом виде, без шифрования. HTTPS работает поверх TLS и защищает соединение: выполняется проверка сертификата, обмен ключами и дальнейшая передача данных в зашифрованном виде.
На картинке — ключевые этапы установления соединения.
Сохрани, чтобы не забыть!
➡️ C# Ready | #ресурс
await using — асинхронно освобождаем ресурсы без лишних try/finally!
Часто мы открываем файлы или сетевые стримы асинхронно, но… освобождаем синхронно, блокируя поток. В .NET есть решение: интерфейс IAsyncDisposable и ключевое слово await using — всё по-современному и без ручного DisposeAsync().
Старая реализация закрывает поток синхронно, заставляя поток ожидать завершения операции, и нагружает планировщик лишними блокировками:
// Было — синхронный Dispose
async Task<long> Old(string p)
{
var s = new FileStream(p, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true);
try { return s.Length; }
finally { s.Dispose(); } // блокирует поток
}
// Стало — await using + DisposeAsync
async Task<long> New(string p)
{
await using var s = new FileStream(p, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true);
return s.Length; // всё асинхронно и лаконично
}
await using автоматически вызывает DisposeAsync() без блокировок и лишнего кода — особенно важно в высоконагруженных сервисах и UI-приложениях.
❤️ Andrew Lock — .NET Escapades — блог и персональный сайт для .NET-разработчиков!
Технический блог от опытного .NET разработчика и Microsoft MVP, где автор делится глубокими практическими заметками, гайдами и идеями по современному разработку с ASP.NET Core, C#, .NET Core/NET 10 и связанным инструментам.
📌 Оставляю ссылочку: andrewlock.net
➡️ C# Ready | #ресурс
Почему async void приводит к потерянным ошибкам?
Иногда хочется быстро сделать асинхронный метод и поставить async void. Сначала всё выглядит нормально, но при ошибке вызывающий код уже не может корректно обработать исключение.
Поэтому баги всплывают позже и разбор занимает больше времени.
Вот как обычно выглядит такая ситуация:
static async void ProcessOrderAsync(int id)
{
await Task.Delay(100);
throw new InvalidOperationException($"Order {id} failed");
}
ProcessOrderAsync(42);
Console.WriteLine("Дальше код идёт как будто всё хорошо");
async void вызывающий код не может дождаться завершения метода. По этой причине ошибка теряет контекст и в логах часто выглядит случайной.Task и явно дождаться выполнения:static async Task ProcessOrderAsync(int id)
{
await Task.Delay(100);
throw new InvalidOperationException($"Order {id} failed");
}
try
{
await ProcessOrderAsync(42);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
async Task. async void оставляйте только для обработчиков событий.
📱 FixedUpdate vs Update: стабильная физика и отзывчивый ввод!
Когда логика и физика живут в правильных циклах, управление остается быстрым, а движение не ломается из-за разного FPS.
В этом гайде:
• Разбираем, почему смешивать физику и ввод в одном методе опасно;
• Показываем рабочую схему с Update и FixedUpdate без конфликтов;
• Объясняем, когда использовать Time.deltaTime и Time.fixedDeltaTime.
❤️ CodeChef: C# with Beginner DSA — это пошаговый учебный на CodeChef
На нём ты найдёшь roadmap из ~6 курсов: от основ C# и логики до Beginner DSA, а дальше — закрепление через сотни задач по DSA/алгоритмам (под интервью и контесты).
📌 Оставляю ссылочку: codechef.com
➡️ C# Ready | #ресурс
Собрал чат-бота за вечер → заработал 9 000₽.
Так и работают специалисты по чат-ботам:
открыл шаблон → собрал бота как конструктор → получил деньги.
Работы — на 2–3 часа.
Оплата — 9–15 000₽ за сборку.
Никакого программирования и долгих задач.
Если умеешь открыть ворд или запустить косынку — справишься.
А спрос сейчас бешеный:
более 10 000 предпринимателей в месяц ищут тех, кто делает ботов и авторассылки.
Это одна из самых простых и пустых ниш в онлайне — бери и зарабатывай.
И главное:
Собрать первого бота без опыта и получить клиента — проще, чем кажется.
Все инструкции лежат здесь:
👉 @other_digital_bot
Кто готов кликать мышкой и брать заказы —
тот спокойно накопит на отдых, машину, квартиру и любые хотелки.
Пробуй: @other_digital_bot
ArrayPool<T> в C#: снижаем нагрузку на GC в горячем коде!
Когда в каждом запросе создаётся новый byte[], приложение начинает чаще упираться в сборку мусора. На небольшом трафике это незаметно, но под нагрузкой появляются лишние паузы.
Обычно код выглядит так:
static void Handle(ReadOnlySpan<byte> payload, Stream output)
{
var buffer = new byte[8192];
payload.CopyTo(buffer);
output.Write(buffer, 0, payload.Length);
}
ArrayPool<byte>.Shared и возвращать его после работы:using System.Buffers;
static void Handle(ReadOnlySpan<byte> payload, Stream output)
{
byte[] buffer = ArrayPool<byte>.Shared.Rent(8192);
try
{
payload.CopyTo(buffer);
output.Write(buffer, 0, payload.Length);
}
finally
{
ArrayPool<byte>.Shared.Return(buffer, clearArray: true);
}
}
finally, иначе эффект от пула быстро пропадёт.
✍️ Отличная статья — про то, как собрать свою первую 2D-игру на MonoGame!
В этой статье:• Поймёшь, как устроен игровой цикл: Initialize → LoadContent → Update → Draw;
• Научишься загружать и рисовать текстуры (спрайты) и управлять позициями объектов;
• Разберёшь основы архитектуры 2D-игры на MonoGame и сделаешь первый рабочий прототип
🔊 Продолжай читать на MonoGame
ReadOnlySpan<char> вместо Substring: парсим строки без лишних аллокаций!
Когда строка режется через Substring, чаще всего создаётся новый объект string, и на потоке логов или CSV это быстро становится заметно по памяти.
Привычный вариант:
string line = "id=42;name=alice";
string idPart = line.Substring(3, 2);
int id = int.Parse(idPart);
ReadOnlySpan<char>.ReadOnlySpan<char> line = "id=42;name=alice";
int sep = line.IndexOf(';');
ReadOnlySpan<char> idPart = line.Slice(3, sep - 3);
int id = int.Parse(idPart);
ReadOnlySpan<char> не хранит данные и только ссылается на источник, поэтому его нельзя держать в полях класса.