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
Это огромная коллекция пошаговых гайдов, где учатся программированию через практику. Проекты реализованы на разных языках, в том числе на C# и C++. Здесь можно попробовать написать собственную базу данных, Git-клиент, веб-сервер, блокчейн, игровой движок, браузер или даже язык программирования.
Оставляю ссылочку: GitHub📱
Please open Telegram to view this post
VIEW IN TELEGRAM
❤14👍7🔥7
Почему CancellationToken бесполезен, если не передать его дальше?
Многие принимают
То есть клиент уже закрыл страницу или отменил запрос, а сервер всё ещё тратит ресурсы на работу, результат которой уже никому не нужен.
Чтобы отмена действительно работала, токен нужно прокидывать до самого места, где выполняется операция.
🔥 Если токен не дошёл до реальной работы — отмена у тебя существует только на бумаге.
➡️ C# Ready | #совет
Многие принимают
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 и других операций, которые можно остановить.Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤4🔥3
Сделаем консольную утилиту на C#, которая за один запуск переименует все файлы в каталоге в выбранном режиме.
В этой задаче:
• Поддержка префикса, суффикса, смены расширения и нумерации файлов.
• Обрабатываем аргументы, фильтруем и сортируем список файлов в папке.
• Генерируем имена, переименовываем файлы, выводим прогресс и ошибки.
Полезно, когда нужно быстро навести порядок в фотоархивах, экспортированных отчётах, логах или бэкапах.
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#, не изменяя их код и не создавая подклассов.
Подключим стандартную библиотеку:
Допустим, у нас есть строка с названием статьи, и мы хотим превратить её в "slug" — пригодную для URL или имён файлов. У стандартного
Создаём статический класс и описываем метод, указав
Теперь мы можем вызывать
Вот что получится при запуске:
🔥 Таким образом ты можешь элегантно добавлять поведение к любым типам — без наследования и без лишнего кода.
➡️ C# Ready | #практика
Сейчас научимся добавлять собственные методы к стандартным типам в 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);
Вот что получится при запуске:
новости-дня-кратко-и-ясно
🔥 Таким образом ты можешь элегантно добавлять поведение к любым типам — без наследования и без лишнего кода.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17❤9🔥5
В этой статье:
• Поймёшь, как устроена базовая сцена в 3D и с чего начать проект на MonoGame;• Разберёшься, как добавить камеру, управление и отрисовку объектов в пространстве;• Посмотришь, как шаг за шагом собрать простой игровой прототип и увидеть результат вживую.🔊 Продолжай читать на Habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍3🔥3👎1
Почему опасно перечислять IEnumerable несколько раз?
Когда мы работаем с
Из-за этого код может выглядеть безобидно, но делать больше работы, чем кажется на первый взгляд.
Здесь последовательность может быть пройдена дважды: сначала в
Если ты понимаешь, что данные понадобятся несколько раз, лучше один раз материализовать их в список и дальше работать уже с ним.
Так код становится честнее: мы явно показываем, что хотим сохранить результат и использовать его дальше без повторного перечисления.
🔥 Если последовательность нужна больше одного раза — лучше сразу зафиксировать её в памяти и не гонять одну и ту же логику повторно.
➡️ C# Ready | #совет
Когда мы работаем с
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);
}
Так код становится честнее: мы явно показываем, что хотим сохранить результат и использовать его дальше без повторного перечисления.
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
Это сайт, где собраны ресурсы для изучения разных языков программирования, включая отдельные подборки по C++ и C#. Позволяет быстро найти платформы, курсы и учебные материалы. По C++ и C#: курсы, видео, полноценные учебные порталы, туториалы и гайды. Можно выбрать подходящий ресурс и начать обучение без долгого поиска.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13❤8👍8
Фильтруем списки эффективно с ToHashSet!
Сейчас научимся быстро отбирать элементы одного списка, проверяя, есть ли они в другом. Это избавит от лишних проходов и ускорит работу кода.
Подключим нужные библиотеки — всё уже есть в стандартной библиотеке:
Допустим, мы хотим оставить только избранные фрукты. Без оптимизации код выглядит так:
Если списки большие,
Теперь преобразуем второй список в
🔥 Без
➡️ C# Ready | #практика
Сейчас научимся быстро отбирать элементы одного списка, проверяя, есть ли они в другом. Это избавит от лишних проходов и ускорит работу кода.
Подключим нужные библиотеки — всё уже есть в стандартной библиотеке:
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 — это почти мгновенная проверка.Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤5🔥4
async/await в C#: почему .Result всё ещё ломает код
Одна из самых частых ошибок в C# — взять асинхронный метод и “быстро” дождаться его через
Проблема в том, что вы смешиваете две разные модели: асинхронное выполнение и синхронное ожидание. В UI это может закончиться фризом, а на сервере — лишней блокировкой потока там, где можно было спокойно продолжать работу.
Плохой вариант выглядит так:
Здесь асинхронный метод превращается в синхронную точку ожидания. Код вроде работает, но именно в таких местах потом начинаются “странные” подвисания и деградация под нагрузкой.
Намного безопаснее дотягивать
Правильнее так:
Если метод внутри асинхронный, наружный API тоже почти всегда должен оставаться асинхронным. Тогда поток не блокируется, а приложение ведёт себя предсказуемо и в UI, и на сервере.
Ещё один полезный ориентир: если рука тянется написать
🔥
➡️ C# Ready | #практика
Одна из самых частых ошибок в 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 часто маскирует проблему, а не решает её.Please open Telegram to view this post
VIEW IN TELEGRAM
❤12👍7🔥5
This media is not supported in your browser
VIEW IN TELEGRAM
Здесь собраны пошаговые гайды по базовому синтаксису C#, объектно-ориентированному программированию, LINQ, async/await, работе с SQLite, файловой системой и многим другим.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11❤6👍5
Почему HashSet лучше List для частых Contains()?
Когда коллекция нужна только для проверки “есть элемент или нет”,
Проблема обычно появляется в циклах, где
Снаружи всё выглядит нормально, но на больших объёмах такой код начинает делать лишнюю работу.
Если порядок элементов не важен и коллекция нужна именно для быстрых проверок, лучше использовать
Так код лучше отражает намерение: мы храним набор значений не ради списка, а ради быстрых проверок на вхождение.
🔥 Если коллекция нужна в первую очередь для
➡️ C# Ready | #совет
Когда коллекция нужна только для проверки “есть элемент или нет”,
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.Please open Telegram to view this post
VIEW IN TELEGRAM
❤14👍3🔥3