csharp_ready | Unsorted

Telegram-канал csharp_ready - C# Ready | Unity

9818

Авторский канал по разработке на C# и Unity. Ресурсы, гайды, задачи, шпаргалки. Информация ежедневно пополняется! Автор: @energy_it РКН: https://clck.ru/3SBaT3 Реклама на бирже: https://telega.in/c/csharp_ready

Subscribe to a channel

C# Ready | Unity

with-выражение: обновляем объект без мутаций и лишнего кода!

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

Раньше приходилось создавать новый объект вручную и копировать остальные свойства:

record User(string Name, int Age, string City);

var user = new User("Анна", 28, "Helsinki");

var updated = new User(
"Анна Петрова",
user.Age,
user.City
);

Console.WriteLine(user);
Console.WriteLine(updated);


Такой код быстро превращается в копипасту: чем больше полей, тем больше риск забыть что-то перенести или случайно перепутать.

С with-выражением можно скопировать объект и изменить только нужные свойства:
record User(string Name, int Age, string City);

var user = new User("Анна", 28, "Helsinki");

var updated = user with { Name = "Анна Петрова" };

Console.WriteLine(user);
Console.WriteLine(updated);


Исходный объект остаётся прежним, а updated — это новая копия с изменённым значением.

🔥 Итог: меньше шаблонного копирования, меньше ошибок и удобный путь к иммутабельному коду.

➡️ C# Ready | #практика

Читать полностью…

C# Ready | Unity

🤨 LINQPad — интерактивная “песочница” для C#/.NET и запросов к базам данных!

Настольный scratchpad от Джозефа Альбахари: можно быстро писать и запускать C#-скрипты, проверять идеи без создания проектов, а ещё — удобно ходить по данным и джойнить сущности через LINQ или писать обычный SQL.

📌 Оставляю ссылочку: linqpad.net

➡️ C# Ready | #ресурс

Читать полностью…

C# Ready | Unity

📂 Шпаргалка по основам C#!

На картинке — насыщенная и компактная памятка по ключевым возможностям языка C#: работа с компилятором из командной строки, базовый синтаксис и управляющие конструкции, циклы и условия, описание классов, методов и свойств, а также делегаты, события, структуры и перечисления.

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

➡️ C# Ready | #ресурс

Читать полностью…

C# Ready | Unity

🎄 Всех с наступающим новым 2025 2026 годом!

Поставлю себе цель: набрать более 20 тысяч подписчиков. Желаю каждому выполнить планы.

Читать полностью…

C# Ready | Unity

Как получить уникальные значения без ручных проверок?

Часто нужно убрать дубликаты: имена пользователей, id, теги.
Иногда для этого пишут такую конструкцию:

if (!list.Contains(x))
list.Add(x);


Это работает, но в Contains список просматривается каждый раз — чем больше данных, тем медленнее. Да и выглядит это как “велосипед”.

Гораздо проще (и читабельнее) использовать готовые инструменты:

Для LINQ — Distinct()
Она сама уберёт дубли и вернёт последовательность уникальных значений:
var unique = names.Distinct().ToList();


Для максимальной скорости — `HashSet`
HashSet<T> из коробки хранит только уникальные элементы, без повторов:
var set = new HashSet<string>(names);


🔥 Итог: когда нужны уникальные значения — начинай с Distinct() или HashSet. Меньше ручных проверок, меньше кода, и алгоритм сразу читается как правило: *“здесь храним только уникальные элементы”*.

➡️ C# Ready | #совет

Читать полностью…

C# Ready | Unity

Span<T> на пальцах — быстрый доступ к данным без лишних аллокаций!

Часто мы режем строки, копируем массивы, делаем Substring и создаём новые объекты там, где можно обойтись без копирования. Это даёт лишние аллокации и нагрузку на GC.

Span<T> позволяет работать с участком памяти (частью массива/строки) как с “окном”, не создавая новые объекты.

Допустим, у нас есть строка, и мы хотим достать из неё только число:

string text = "User:42;Role:Admin";


Обычно делают так (и это создаёт новую строку):
string idText = text.Substring(5, 2);
int id = int.Parse(idText);
Console.WriteLine(id);


Теперь сделаем то же самое через Span<char> — без Substring:
ReadOnlySpan<char> span = text.AsSpan();

// берём "42" как срез
ReadOnlySpan<char> idSpan = span.Slice(5, 2);

// парсим напрямую из Span
int userId = int.Parse(idSpan);
Console.WriteLine(userId);


Результат:
42


🔥Span<T> (и ReadOnlySpan<T>) позволяет брать срезы без копирования данных. Это особенно полезно в горячих участках кода: парсинг, обработка строк, сетевые протоколы, высоконагруженные сервисы.

➡️ C# Ready | #практика

Читать полностью…

C# Ready | Unity

☕️ Awesome-Shell — топовая коллекция утилит, скриптов и приёмов для терминала!

Здесь собраны десятки CLI-инструментов, полезные bash/zsh-скрипты, практичные сниппеты и лайфхаки, которые ускоряют работу. Отличный набор для автоматизации, оптимизации и прокачки навыков работы с командной строкой.

Оставляю ссылочку: GitHub 📱


➡️ C# Ready | #ресурс

Читать полностью…

C# Ready | Unity

😎 Отличная статья — как перестать вручную писать конструкторы и доверить это Source Generator’у.

В этой статье:

• Поймёшь, зачем генерация конструкторов снижает бойлерплейт и ошибки
• Увидишь, как атрибуты описывают зависимости и правила инъекции
• Разберёшь подключение генератора, ограничения, нюансы и реальные кейсы

🔊 Продолжай читать на Habr!


➡️ C# Ready | #статья

Читать полностью…

C# Ready | Unity

📂 Шпаргалка по Core C# и .NET!

На картинке — компактный quick reference по базовым вещам в C#: примитивные типы и их размеры, работа с массивами, частые операции со строками, форматирование чисел и дат, основы регулярных выражений

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

➡️ C# Ready | #ресурс

Читать полностью…

C# Ready | Unity

☕️ Смотрите что нашел — Explainshell.

Вводишь любую команду в терминале, и он по частям объясняет, что делает каждая часть. Не просто man-ка, а понятный синтакс-анализ.

Особенно кайф для тех, кто работает в Linux/DevOps/CI среде и хочет разбираться, а не наугад копипастить из StackOverflow.

📌 Оставляю ссылочку: explainshell.com

➡️ C# Ready | #ресурс

Читать полностью…

C# Ready | Unity

Обрабатываем ошибки с try-catch-finally!

Сейчас научимся ловить ошибки во время выполнения программы с помощью конструкции try-catch. Это особенно полезно, когда пользователь может ввести некорректные данные — например, буквы вместо чисел.

Подключим нужные библиотеки — всё уже есть в стандартной библиотеке:

using System;


Допустим, мы хотим преобразовать строку в число. Если строка — не число, программа «упадёт»:
string input = "abc";
int number = Convert.ToInt32(input); // тут возникнет ошибка


Чтобы программа не завершалась с ошибкой, обернём этот код в try-catch. Если произойдёт исключение, оно будет поймано и обработано:
try {
string input = "abc";
int number = Convert.ToInt32(input);
Console.WriteLine($"Число: {number}");
}


Если строка не может быть преобразована в число, будет выброшено исключение типа FormatException.
catch (FormatException) {
Console.WriteLine("Ошибка: введена нечисловая строка.");
}


И наконец, добавим блок finally. Он выполняется всегда — даже если произошла ошибка.
finally {
Console.WriteLine("Завершено выполнение блока.");
}


🔥 Без try-catch программа завершилась бы аварийно. А с обработкой исключений — работает стабильно, даже при ошибочном вводе.

➡️ C# Ready | #практика

Читать полностью…

C# Ready | Unity

Как не писать if (x == null) throw ... вручную?

В C# мы постоянно защищаемся от null: в публичных методах, сервисах, хендлерах, контроллерах. И почти в каждом месте повторяется один и тот же шаблон:

if (options == null)
throw new ArgumentNullException(nameof(options));


Это работает, но:

• код раздувается от однотипных проверок,
• легко забыть nameof(...) или написать не то имя,
• “полезная” логика тонет в бойлерплейте.

В современных версиях .NET есть короткий и безопасный вариант:
ArgumentNullException.ThrowIfNull(options);


Он делает ровно то же самое — бросает ArgumentNullException, если аргумент null, — но запись становится в разы чище.

🔥 Итог: вместо ручного if (...) throw ... используй ArgumentNullException.ThrowIfNull(x) — меньше шума, меньше копипасты, проще читать метод с первого взгляда.

➡️ C# Ready | #совет

Читать полностью…

C# Ready | Unity

👩‍💻 IDisposable без лишней магии!

В этой шпаргалке — наглядное объяснение того, как в .NET правильно освобождать ресурсы: чем отличается Dispose от финализации, как работает using, когда нужен await using и почему IAsyncDisposable важен для современного асинхронного кода.

➡️ C# Ready | #шпора

Читать полностью…

C# Ready | Unity

Разница между out и ref — когда что использовать?

В C# оба ключевых слова позволяют передавать параметры по ссылке, но работают они по-разному. Из-за этого их часто путают — особенно на собеседованиях.

Разберёмся на простом и наглядном примере.

Создадим метод с параметром ref. В этом случае переменная обязана быть инициализирована до вызова метода:

void Increment(ref int number)
{
number++;
}


Используем его:
int value = 5;
Increment(ref value);
Console.WriteLine(value);


Вывод в консоли:
6


Теперь сделаем похожий метод, но уже с out. Здесь метод обязан присвоить значение параметру внутри себя:
void CreateValue(out int number)
{
number = 10;
}


Вызовем его — обратите внимание, что переменную заранее инициализировать не нужно:
int result;
CreateValue(out result);
Console.WriteLine(result);


Результат:
10


🔥 Главное различие:
ref — работает с уже существующим значением
out — используется, когда метод создаёт значение и возвращает его через параметр

➡️ C# Ready | #практика

Читать полностью…

C# Ready | Unity

Retry с Polly — переживаем временные ошибки без ручных try/catch!

Иногда внешний API или сервис отвечает ошибкой (500, timeout), но при повторной попытке всё работает. Оборачивать каждый запрос в try/catch и писать циклы — неудобно. Проще использовать Polly и задать политику повторных попыток.

Сначала подключим нужные пакеты и пространства имён:

using System;
using System.Net.Http;
using Polly;
using Polly.Retry;


Создадим политику retry: при ошибке запроса пробуем ещё 3 раза с паузой в 1 секунду:
RetryPolicy retryPolicy = Policy
.Handle<HttpRequestException>()
.WaitAndRetry(
retryCount: 3,
sleepDurationProvider: _ => TimeSpan.FromSeconds(1),
onRetry: (exception, timeSpan, retryCount, context) =>
{
Console.WriteLine($"Повтор #{retryCount} через {timeSpan.TotalSeconds} сек...");
});


Теперь используем эту политику при выполнении HTTP-запроса:
string GetDataWithRetry()
{
return retryPolicy.Execute(() =>
{
Console.WriteLine("Делаем запрос...");
return CallUnstableService();
});
}


Для примера сделаем простую «заглушку» нестабильного сервиса:
int attempt = 0;

string CallUnstableService()
{
attempt++;

if (attempt < 3)
throw new HttpRequestException("Сервис временно недоступен");

return "Данные успешно получены";
}


Теперь посмотрим, как это работает:
Console.WriteLine(GetDataWithRetry());


Возможный вывод в консоли:
Делаем запрос...
Повтор #1 через 1 сек...
Делаем запрос...
Повтор #2 через 1 сек...
Делаем запрос...
Данные успешно получены


🔥 Обрати внимание: код запроса остался чистым — Polly сам управляет повторами и задержками, без лишних try/catch.

➡️ C# Ready | #практика

Читать полностью…

C# Ready | Unity

Как перестать писать “магические строки” в логах и ошибках?

Часто в логирование и исключения попадают строки вроде "CreateUser" или "UserService" — и как только ты переименовал метод/файл, эти строки не обновились. В итоге логи врут, а поиск по проекту ломается.

Для имён используй nameof() — он безопасен при рефакторинге:

throw new InvalidOperationException(nameof(CreateUser));


А чтобы автоматически подставлять место вызова (метод/файл/строку) — есть caller info атрибуты:
[CallerMemberName] string member = "",
[CallerFilePath] string file = "",
[CallerLineNumber] int line = 0


Теперь ты пишешь просто:
Log.Info("User created");

а в выводе уже будет, откуда это пришло.

🔥 Как итог меньше ручных строк, логи и сообщения не “стареют” после переименований, а диагностика становится точнее без дополнительного кода.

➡️ C# Ready | #совет

Читать полностью…

C# Ready | Unity

👩‍💻 Params vs ReadOnlySpan: передай значения без лишних массивов!

params удобен, но часто создаёт временный массив — в горячем коде это лишние аллокации и нагрузка на GC. Есть простой трюк: принимать ReadOnlySpan<T> и передавать набор значений без new.

В этом посте:

• Поймём, почему params может незаметно создавать массивы;

• Посмотрим, как заменить это на ReadOnlySpan<T> и stackalloc;

• Разберём ограничения Span и где его нельзя использовать.


После гайда вы сможете делать такие “мелкие” оптимизации там, где они реально дают прирост — без усложнения логики и без магии.

➡️ C# Ready | #гайд

Читать полностью…

C# Ready | Unity

List patterns в C# 11: проверяем массивы и списки без if-каши!

Иногда нужно быстро понять, что лежит в коллекции: пустая ли она, с чего начинается, чем заканчивается, есть ли конкретная “форма” данных.

Раньше это превращалось в проверки Length и индексов:

int[] numbers = { 0, 5, 7, 10 };

if (numbers.Length == 0)
Console.WriteLine("Пусто");
else if (numbers.Length >= 1 && numbers[0] == 0)
Console.WriteLine("Начинается с 0");
else if (numbers.Length >= 1 && numbers[^1] == 10)
Console.WriteLine("Заканчивается на 10");
else if (numbers.Length == 3 && numbers[2] == 10)
Console.WriteLine("Третий элемент = 10");
else
Console.WriteLine("Другая форма");


Чем больше условий, тем быстрее это разрастается и становится трудно читать.

В C# 11 появились list patterns, которые позволяют матчить коллекцию прямо по её “форме”:
int[] numbers = { 0, 5, 7, 10 };

var result = numbers switch
{
[] => "Пусто",
[0, ..] => "Начинается с 0",
[.., 10] => "Заканчивается на 10",
[_, _, 10] => "Третий элемент = 10",
_ => "Другая форма"
};

Console.WriteLine(result);


Здесь _ означает “любой элемент”, а .. означает “любое количество элементов” между ними.

🔥 В итоге вместо проверок длины и индексов ты пишешь условия так, как думаешь о данных: по форме коллекции.

➡️ C# Ready | #практика

Читать полностью…

C# Ready | Unity

❤️ Scrimba — интерактивное обучение программированию!

Если обычные видеоуроки не заходят и хочется больше практики — Scrimba решает эту задачу. Здесь обучение построено так, что ты не просто смотришь объяснение, а сразу работаешь с кодом прямо в уроке: меняешь примеры, запускаешь и смотришь результат. На платформе есть множество языков и технологий.

📌 Оставляю ссылочку: scrimba.com

➡️ C# Ready | #ресурс

Читать полностью…

C# Ready | Unity

✍️ Red Blob Games — полезный сайт для визуального понимания алгоритмов!

Если тебе сложно понять алгоритмы по учебникам — этот ресурс решает проблему. Автор объясняет графы, геометрию, деревья, меши из геймдева через понятные визуализации и интерактивы. Сложные идеи здесь раскладываются на простые шаги.

📌 Оставляю ссылочку: redblobgames.com

➡️ C# Ready | #ресурс

Читать полностью…

C# Ready | Unity

👩‍💻 Шпаргалка по Git!

На картинке — компактная карта команд Git, где всё разложено по логике работы: от создания репозитория и просмотра истории до внесения изменений, откатов, обновления из удалённого репо, работы с ветками и публикации результата.

Сохрани, чтобы быстро освежить в памяти нужный шаг, когда Git внезапно “начинает жить своей жизнью”

➡️ C# Ready | #ресурс

Читать полностью…

C# Ready | Unity

Lazy<T>: создаём объект только тогда, когда он реально нужен!

Иногда объект создаётся «на всякий случай», хотя по факту используется редко (например, тяжёлый сервис, настройки, конфиг, загрузка файла). В итоге мы тратим время и ресурсы при старте приложения зря.

Lazy<T> решает это просто: объект создаётся только при первом обращении к нему.

Допустим, у нас есть «тяжёлый» объект, который долго создаётся:

class HeavyService
{
public HeavyService()
{
Console.WriteLine("Создаём HeavyService (дорого)...");
// здесь могла бы быть долгая инициализация
}

public string GetData() => "Данные получены";
}


Теперь создадим Lazy<HeavyService>. Обрати внимание: конструктор HeavyService не вызывается сразу:
var lazyService = new Lazy<HeavyService>(() => new HeavyService());
Console.WriteLine("Lazy создан, но сервис ещё не создан");


А теперь впервые обратимся к объекту через .Value — вот тут он и создастся:
Console.WriteLine(lazyService.Value.GetData());


Возможный вывод в консоли:
Lazy создан, но сервис ещё не создан
Создаём HeavyService (дорого)...
Данные получены


🔥 Lazy<T> помогает ускорить старт приложения и не создавать тяжёлые объекты заранее — они появятся только если реально понадобятся.

➡️ C# Ready | #практика

Читать полностью…

C# Ready | Unity

Как не писать Any() перед First()?

Частая привычка — сначала проверить коллекцию, а потом взять первый элемент:

if (items != null && items.Any())
{
var first = items.First();
// ...
}


Проблема в том, что это:

• добавляет лишний шум в код,
• нередко делает двойной проход по источнику (особенно если это IEnumerable, LINQ-запрос, поток данных),
• усложняет чтение: полезная логика прячется за проверками.

Вместо связки Any() + First() обычно достаточно сразу использовать безопасный вариант:
var first = items.FirstOrDefault();
if (first is null) return; // или другой fallback


Если тебе нужно “взять элемент или вернуть дефолт”, это читается как правило и не заставляет выполнять одну и ту же работу дважды.

🔥 Итог: не проверяй Any() перед First() — чаще бери FirstOrDefault() (или SingleOrDefault() для “должен быть один”) и обработай null/default один раз в понятном месте.

➡️ C# Ready | #совет

Читать полностью…

C# Ready | Unity

👩‍💻 Буферы, которые не засоряют память!

ArrayPool особенно хорош в “горячем” коде, где буферы создаются сотни/тысячи раз: сериализация, парсинг, сетевые пакеты, кодирование строк.

В что важно знать:

• Rent() может вернуть массив больше запрошенного;

• Return() — всегда (лучше через try/finally);

• После Return() массив использовать нельзя; для секретов — clearArray: true


Если у тебя много временных byte[]/char[] — ArrayPool<T> почти всегда даёт профит, но требует дисциплины.

➡️ C# Ready | #гайд

Читать полностью…

C# Ready | Unity

Почему async void почти всегда ошибка?

При работе с асинхронным кодом в C# многие по привычке пишут async void, не задумываясь о последствиях. На первый взгляд всё работает, но такие методы могут привести к трудноуловимым багам.

Разберёмся, в чём проблема и как правильно писать асинхронные методы.

Создадим метод с async void:

async void DoWorkAsync()
{
await Task.Delay(1000);
throw new Exception("Ошибка внутри async void");
}


Вызовем его:
DoWorkAsync();
Console.WriteLine("Метод вызван");


При запуске приложение завершится с ошибкой, и мы не сможем поймать исключение через try/catch.

Теперь перепишем метод правильно — с async Task:
async Task DoWorkAsync()
{
await Task.Delay(1000);
throw new Exception("Ошибка внутри async Task");
}


Вызовем его с обработкой ошибок:
try
{
await DoWorkAsync();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}


Результат в консоли:
Ошибка внутри async Task


🔥 async void нельзя await и в нём невозможно корректно обработать исключения. Используй async Task, а async void оставляй только для обработчиков событий.

➡️ C# Ready | #практика

Читать полностью…

C# Ready | Unity

👍 Отличная статья — про инкрементные Source Generators: как ускорить генерацию и не грузить IDE лишним!

В этой статье:

• Разобраться, чем incremental отличается от классических генераторов
• Увидеть, как собирается пайплайн: провайдеры, трансформации
• Понять практические кейсы: генерация boilerplate, DSL-подходы

🔊 Продолжай читать на Habr!


➡️ C# Ready | #статья

Читать полностью…

C# Ready | Unity

📂 Напоминалка по REST API

На картинке — компактная шпаргалка про то, каким должен быть “правильный” REST: запросы без состояния, предсказуемые URL, безопасность через HTTPS, версионирование, аккуратная работа с коллекциями (фильтры и пагинация) и понятная логика взаимодействия клиента с сервером.

Сохрани, чтобы быстро сверяться при проектировании и ревью API

➡️ C# Ready | #ресурс

Читать полностью…

C# Ready | Unity

❤️ ShaderToy — шейдеры в браузере и море вдохновения!

Это платформа, где можно писать и запускать GLSL-шейдеры прямо в браузере: огромная библиотека работ сообщества, живые демки, код рядом с результатом, плюс удобный редактор для экспериментов со светом, шумами, пост-эффектами и процедурной графикой.

📌 Оставляю ссылочку: shadertoy.com

➡️ C# Ready | #ресурс

Читать полностью…

C# Ready | Unity

Как не ловить NullReferenceException в цепочках user.Profile.Address.City?

Когда данные приходят из API/БД/ввода пользователя — в любой момент может прилететь null. И вместо простого чтения свойства появляется лес из проверок:

string city;

if (user != null &&
user.Profile != null &&
user.Profile.Address != null &&
user.Profile.Address.City != null)
{
city = user.Profile.Address.City;
}
else
{
city = "Не указан";
}


С null-conditional оператором ?. и значением по умолчанию через ?? то же самое пишется коротко и читаемо:
var city = user?.Profile?.Address?.City ?? "Не указан";


?. работает как “безопасная точка”: если слева null — выражение дальше не падает и возвращает null.
А ?? подставляет значение, если результат оказался null.

🔥 Итог: меньше шума, меньше ручных проверок, меньше шансов словить NullReferenceException. Код читается как правило: «если чего-то нет — подставь дефолт».

➡️ C# Ready | #совет

Читать полностью…

C# Ready | Unity

☕️ Нашел вам разбор ConfigureAwait без мифов — когда он нужен, а когда нет!

В этой статье:
• Что делает SynchronizationContext и почему это важно для await
• Когда ConfigureAwait(false) даёт пользу, а когда ломает логику
• Особые случаи: IAsyncEnumerable, библиотеки и “контекстные” приложения

🔊 Продолжай читать на Habr!


➡️ C# Ready | #статья

Читать полностью…
Subscribe to a channel