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

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

РКН: https://clck.ru/3SBaT3
Download Telegram
👩‍💻 string vs StringBuilder без лишней магии!

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

➡️ C# Ready | #шпора
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🤝19👍7❤6🔥5
This media is not supported in your browser
VIEW IN TELEGRAM
✍️ Build Your Own X — освойте программирование, воссоздав любимые технологии с нуля!

Это огромная коллекция пошаговых гайдов, где учатся программированию через практику. Проекты реализованы на разных языках, в том числе на C# и C++. Здесь можно попробовать написать собственную базу данных, Git-клиент, веб-сервер, блокчейн, игровой движок, браузер или даже язык программирования.

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


➡️ C# Ready | #репозиторий
Please open Telegram to view this post
VIEW IN TELEGRAM
❤14👍7🔥7
Почему CancellationToken бесполезен, если не передать его дальше?

Многие принимают CancellationToken в методе, но потом просто не используют его в реальной async-операции. В итоге создаётся ощущение, что отмена у нас поддерживается, хотя на практике запрос в базу или внешний сервис всё равно продолжает выполняться.

То есть клиент уже закрыл страницу или отменил запрос, а сервер всё ещё тратит ресурсы на работу, результат которой уже никому не нужен.
public async Task<List<Order>> GetOrders(CancellationToken ct)
{
return await _db.Orders
.Where(x => x.IsActive)
.ToListAsync();
}


Чтобы отмена действительно работала, токен нужно прокидывать до самого места, где выполняется операция.
public async Task<List<Order>> GetOrders(CancellationToken ct)
{
return await _db.Orders
.Where(x => x.IsActive)
.ToListAsync(ct);
}


CancellationToken полезен не тогда, когда он просто есть в сигнатуре, а тогда, когда реально доходит до ToListAsync, SendAsync, ReadAsync и других операций, которые можно остановить.

🔥 Если токен не дошёл до реальной работы — отмена у тебя существует только на бумаге.

➡️ C# Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤4🔥3
👍19🤝7🔥6❤1
👩‍💻 Массовое переименование файлов в папке!

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

В этой задаче:
• Поддержка префикса, суффикса, смены расширения и нумерации файлов.

• Обрабатываем аргументы, фильтруем и сортируем список файлов в папке.

• Генерируем имена, переименовываем файлы, выводим прогресс и ошибки.


Полезно, когда нужно быстро навести порядок в фотоархивах, экспортированных отчётах, логах или бэкапах.

➡️ C# Ready | #задача
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍6❤4
Расширяем string своим методом — ToSlug.

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

Подключим стандартную библиотеку:
using System;


Допустим, у нас есть строка с названием статьи, и мы хотим превратить её в "slug" — пригодную для URL или имён файлов. У стандартного string такого метода нет, но мы можем добавить его сами через метод-расширение.

Создаём статический класс и описываем метод, указав this перед первым параметром:
static class StringExtensions
{
static string ToSlug(this string input)
{
return input
.ToLower()
.Replace(" ", "-")
.Replace(".", "")
.Replace(",", "");
}
}


Теперь мы можем вызывать .ToSlug() прямо у строки — будто это встроенный метод:
string headline = "Новости дня, кратко и ясно.";
string slug = headline.ToSlug();
Console.WriteLine(slug);


Вот что получится при запуске:
новости-дня-кратко-и-ясно


🔥 Таким образом ты можешь элегантно добавлять поведение к любым типам — без наследования и без лишнего кода.

➡️ C# Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17❤9🔥5
😍 Отличная статья — про то, как сделать свою первую 3D-игру на MonoGame!

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

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

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


➡️ C# Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍3🔥3👎1
Почему опасно перечислять IEnumerable несколько раз?

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

Из-за этого код может выглядеть безобидно, но делать больше работы, чем кажется на первый взгляд.
var users = GetUsers()
.Where(x => x.IsActive);

if (users.Any())
{
Console.WriteLine(users.Count());
}


Здесь последовательность может быть пройдена дважды: сначала в Any(), потом ещё раз в Count(). Если источник данных тяжёлый — например, запрос, генератор или цепочка LINQ с вычислениями — это уже лишняя работа, которую не видно сразу.

Если ты понимаешь, что данные понадобятся несколько раз, лучше один раз материализовать их в список и дальше работать уже с ним.
var users = GetUsers()
.Where(x => x.IsActive)
.ToList();

if (users.Count > 0)
{
Console.WriteLine(users.Count);
}


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

🔥 Если последовательность нужна больше одного раза — лучше сразу зафиксировать её в памяти и не гонять одну и ту же логику повторно.

➡️ C# Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥5❤4🤝1
This media is not supported in your browser
VIEW IN TELEGRAM
☕️ Fruntend — подборка лучших ресурсов для изучения языков!

Это сайт, где собраны ресурсы для изучения разных языков программирования, включая отдельные подборки по C++ и C#. Позволяет быстро найти платформы, курсы и учебные материалы. По C++ и C#: курсы, видео, полноценные учебные порталы, туториалы и гайды. Можно выбрать подходящий ресурс и начать обучение без долгого поиска.

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

➡️ C# Ready | #сайт
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13❤8👍8
Фильтруем списки эффективно с ToHashSet!

Сейчас научимся быстро отбирать элементы одного списка, проверяя, есть ли они в другом. Это избавит от лишних проходов и ускорит работу кода.

Подключим нужные библиотеки — всё уже есть в стандартной библиотеке:
using System;
using System.Collections.Generic;
using System.Linq;


Допустим, мы хотим оставить только избранные фрукты. Без оптимизации код выглядит так:
List<string> fruits = new() { "apple", "banana", "mango", "orange" };
string[] favorite = { "banana", "kiwi", "orange" };

var selected = fruits.Where(f => favorite.Contains(f)).ToList();


Если списки большие, Contains() будет работать медленно — каждый раз проходит по массиву.

Теперь преобразуем второй список в HashSet — поиск в нём быстрее:
List<string> fruits = new() { "apple", "banana", "mango", "orange" };
string[] favorite = { "banana", "kiwi", "orange" };

HashSet<string> favSet = favorite.ToHashSet();

var selected = fruits.Where(f => favSet.Contains(f)).ToList();


🔥 Без ToHashSet() код искал «банан» в массиве снова и снова. С HashSet — это почти мгновенная проверка.

➡️ C# Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤5🔥4
📂 Напоминалка для работы с Big O Notation!

Например, O(1) — выполняется за постоянное время, а O(n) растёт линейно от размера входных данных.

На картинке — основные виды сложности, которые чаще всего встречаются в алгоритмах и структурах данных.

Сохрани, чтобы не забыть!

➡️ C# Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16❤10🔥10🤝1
async/await в C#: почему .Result всё ещё ломает код

Одна из самых частых ошибок в C# — взять асинхронный метод и “быстро” дождаться его через .Result или .Wait(). На первый взгляд это удобно, но на практике такой код легко приводит к зависаниям, блокировкам и просадке по производительности.

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

Плохой вариант выглядит так:
public string LoadData()
{
return GetDataAsync().Result;
}

private async Task<string> GetDataAsync()
{
await Task.Delay(100);
return "done";
}


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

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

Правильнее так:
public async Task<string> LoadDataAsync()
{
return await GetDataAsync();
}

private async Task<string> GetDataAsync()
{
await Task.Delay(100);
return "done";
}


Если метод внутри асинхронный, наружный API тоже почти всегда должен оставаться асинхронным. Тогда поток не блокируется, а приложение ведёт себя предсказуемо и в UI, и на сервере.

Ещё один полезный ориентир: если рука тянется написать .Result, чаще всего это сигнал, что архитектурно async нужно поднять выше, а не “прижать” в текущем месте.

🔥.Result часто маскирует проблему, а не решает её.

➡️ C# Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
❤12👍7🔥5
This media is not supported in your browser
VIEW IN TELEGRAM
😎 ZetCode — это крутой справочник с подробными туториалами и примерами кода!

Здесь собраны пошаговые гайды по базовому синтаксису C#, объектно-ориентированному программированию, LINQ, async/await, работе с SQLite, файловой системой и многим другим.

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

➡ C# Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11❤6👍5
Почему HashSet лучше List для частых Contains()?

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

Проблема обычно появляется в циклах, где Contains() вызывается снова и снова.
var ids = blockedUsers.Select(x => x.Id).ToList();

foreach (var order in orders)
{
if (ids.Contains(order.UserId))
{
order.MarkForReview();
}
}


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

Если порядок элементов не важен и коллекция нужна именно для быстрых проверок, лучше использовать HashSet.
var ids = blockedUsers.Select(x => x.Id).ToHashSet();

foreach (var order in orders)
{
if (ids.Contains(order.UserId))
{
order.MarkForReview();
}
}


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

🔥 Если коллекция нужна в первую очередь для Contains(), это почти всегда хороший повод выбрать HashSet.

➡️ C# Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
❤14👍3🔥3
📂 Напоминалка по архитектуре систем!

Например, Load Balancing распределяет нагрузку между серверами, а Caching помогает ускорить ответы за счёт хранения данных в памяти.

На картинке — 12 основных концепций, которые должен понимать каждый разработчик.

Сохрани, чтобы не потерять!

➡ C# Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤8🔥7