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

Автор: @energy_c

РКН: https://clck.ru/3SBaT3
Download Telegram
👩‍💻 Сегодня рассмотрим Channel<T> — безопасная асинхронная очередь задач в .NET

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

Что важно знать:

Работает без ручных блокировок и сложных синхронных вызовов.

Позволяет автоматически замедлять отправку при перегрузке памяти.

Обеспечивает плавную передачу данных между параллельными задачами.


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

C# Ready | #гайд
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥53👍2
FirstOrDefault() может вернуть null!

В C# часто ищут элемент в коллекции через LINQ:
var user = users.FirstOrDefault(u => u.Id == id);


Если пользователь найден то всё хорошо.

Но если подходящего элемента нет, FirstOrDefault() вернёт значение по умолчанию.

Для ссылочных типов это обычно:
null


Поэтому такой код может упасть:
Console.WriteLine(user.Name);


Если user оказался null, получим NullReferenceException.

Лучше явно обработать отсутствие результата:
var user = users.FirstOrDefault(u => u.Id == id);

if (user is null)
{
return;
}


Или выбросить понятную ошибку:
var user = users.FirstOrDefault(u => u.Id == id)
?? throw new InvalidOperationException("User not found");


Это особенно важно в API, сервисах, обработчиках команд и бизнес-логике.

➡️ C# Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
11👍9🔥4
Почему технические строки не стоит сравнивать через ToLower()?

Для проверки логина, роли или кода часто пишут так:

if (role.ToLower() == "admin")
{
GrantAccess();
}


Код работает во многих случаях, но ToLower() создаёт новую строку и использует правила текущей культуры приложения.

Для обычного текста это может быть полезно. Но логины, роли, ключи конфигурации, HTTP-заголовки и другие технические значения обычно должны сравниваться по стабильным правилам, независимо от языка системы.

Для этого лучше явно указать тип сравнения:

if (string.Equals(role, "admin", StringComparison.OrdinalIgnoreCase))
{
GrantAccess();
}


OrdinalIgnoreCase не создаёт промежуточную строку и выполняет регистронезависимое порядковое сравнение. Поведение не изменится после запуска приложения на сервере с другой локалью.

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

➡️ C# Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍86🔥4
Теперь небольшую программу на C# можно запустить прямо из одного файла!

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

• Как работают File-Based Apps в .NET 10
• Как запустить .cs-файл без создания отдельного проекта
• Каким способом подключать NuGet-пакеты и дополнительные настройки
• Когда такой формат удобен для скриптов, автоматизации и быстрых экспериментов

Получается знакомая простота скриптовых языков, но с возможностями C# и всей экосистемой .NET.

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


➡️ C# Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9👍65
Почему технические строки не стоит сравнивать через ToLower()?

Для проверки логина, роли или кода часто пишут так:

if (role.ToLower() == "admin")
{
GrantAccess();
}


Код работает во многих случаях, но ToLower() создаёт новую строку и использует правила текущей культуры приложения.

Для обычного текста это может быть полезно. Но логины, роли, ключи конфигурации, HTTP-заголовки и другие технические значения обычно должны сравниваться по стабильным правилам, независимо от языка системы.

Для этого лучше явно указать тип сравнения:

if (string.Equals(role, "admin", StringComparison.OrdinalIgnoreCase))
{
GrantAccess();
}


OrdinalIgnoreCase не создаёт промежуточную строку и выполняет регистронезависимое порядковое сравнение. Поведение не изменится после запуска приложения на сервере с другой локалью.

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

➡️ C# Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍64🔥4
This media is not supported in your browser
VIEW IN TELEGRAM
❤️‍🔥"Это разъ*бный сетап, бро!" 😤

Так сказал мой друг из Африки, когда увидел этот стол)
Не знаю уж че за сетап, меня зовут Саша и качественную необычную мебель из натурального дерева я делаю уже больше 12-ти лет, столько же занимаюсь и темой здоровья.

Когда я услышал, что до 10% смертности связано с сидячим образом жизни, меня это поразило и я задался целью делать максимально функциональные и полезные рабочие пространства, ибо геморрой в 30 это конечно довольно нишево, но все же сомнительно 😂

Ну а собрать такой комплект под свои задачи и при этом сразу прикинуть цены вы можете в удобном Mini App конструкторе
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21🔥1
Отправляем несколько HTTP-запросов параллельно на C#!

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

Создадим HttpClient:
using var client = new HttpClient
{
Timeout = TimeSpan.FromSeconds(10)
};


Запустим три запроса без немедленного ожидания результата:
Task<string> usersTask =
client.GetStringAsync(usersUrl);

Task<string> ordersTask =
client.GetStringAsync(ordersUrl);

Task<string> ratesTask =
client.GetStringAsync(ratesUrl);


Теперь все операции уже выполняются параллельно. Дождёмся завершения всей группы:
await Task.WhenAll(
usersTask,
ordersTask,
ratesTask
);


Получим готовые результаты:
string users = await usersTask;
string orders = await ordersTask;
string rates = await ratesTask;


Если каждый запрос занимает около секунды, последовательное выполнение продлится примерно три секунды, а параллельное около одной.

Добавим ограничение общего времени ожидания:
using var cts =
new CancellationTokenSource(
TimeSpan.FromSeconds(5)
);


Передадим токен отмены запросу:
string data = await client.GetStringAsync(
usersUrl,
cts.Token
);


Так приложение сможет прекратить операцию, если внешний сервис отвечает слишком долго.

➡️ C# Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥52
Шпаргалка по форматированию даты и времени в C#!

Например, dd.MM.yyyy выведет дату с числом, месяцем и годом, HH:mm покажет время в 24-часовом формате, а MMM и MMMM позволяют получить сокращённое или полное название месяца.

На картинке спецификаторы для дня, месяца, года, часов, минут, секунд, долей секунды, часового пояса и AM/PM. Для каждого варианта приведены готовый формат и пример результата.

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

➡️ C# Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥73
Почему with у record не создаёт глубокую копию?

Выражение with удобно использовать для создания изменённой копии record:
var updated = user with
{
Name = "Alex"
};


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

Рассмотрим record со списком:
record User(
string Name,
List<string> Roles
);


Создадим его копию и изменим список:
var original = new User(
"Alex",
new() { "read" }
);

var copy = original with { };

copy.Roles.Add("write");


Изменение появится и в исходном объекте:
Console.WriteLine(
original.Roles.Count
);
// 2


Причина в том, что original.Roles и copy.Roles ссылаются на один экземпляр List<string>.

Если списки должны быть независимыми, скопируйте коллекцию явно:
var copy = original with
{
Roles = new List<string>(
original.Roles
)
};


Другой вариант использовать неизменяемые коллекции:
record User(
ImmutableArray<string> Roles
);

var copy = original with
{
Roles = original.Roles.Add("write")
};


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

➡️ C# Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥53
8👍6🔥4🤝1
Интересный разбор того, как сегодня создавать игры на C# без готового движка!

В этой статье:
• Почему C# подходит для небольших кроссплатформенных игр
• Как SDL3 закрывает окна, ввод, контроллеры и рендеринг
• Как организовать загрузку ассетов и собрать собственный редактор на Dear ImGui

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


➡️ C# Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
👍74🔥4
IT мероприятия 🤘

Всё самое интересное для карьеры в IT: митапы, хакатоны, конференции, стажировки и обучение.

Подписывайся 🤘

1. Москва
2. Санкт-Петербург
3. Для стажеров и студентов
Please open Telegram to view this post
VIEW IN TELEGRAM
CancellationToken должен проходить через всю цепочку вызовов!

Само наличие CancellationToken в параметрах ещё не делает операцию отменяемой:
async Task SyncAsync(CancellationToken token)
{
var data = await LoadAsync();
await SaveAsync(data);
}


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

Токен нужно передавать во все операции, которые поддерживают отмену:
var data = await LoadAsync(token);
await SaveAsync(data, token);
await Task.Delay(500, token);


Для вычислений без await запрос отмены необходимо проверять вручную:
foreach (var item in items)
{
token.ThrowIfCancellationRequested();
Process(item);
}


Отмена в .NET кооперативная: Cancel() не останавливает код принудительно. Он только сообщает операциям, что работу следует завершить.

Для собственного таймаута можно создать источник отмены:
using var timeout = new CancellationTokenSource(
TimeSpan.FromSeconds(10)
);

await SyncAsync(timeout.Token);


Если одновременно нужен токен вызывающего кода и внутренний таймаут, их можно объединить:
using var linked = CancellationTokenSource
.CreateLinkedTokenSource(token, timeout.Token);

await SyncAsync(linked.Token);


Передавайте CancellationToken до самого нижнего отменяемого вызова, иначе API обещает отмену, но фактическая работа продолжается.

➡️ C# Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
8👍4🔥3
«Снова в школу!» – звучит тревожно.

Но в магистратуре МИФИ и Школы 21 «Управление внедрением искусственного интеллекта в бизнес» совсем другая атмосфера: тут нет страха ошибки и ощущения, что зря тратишь время.

Зато есть рабочая среда, поддержка единомышленников и уверенность, что растёшь.

Что внутри программы:

— не просто алгоритмы, а живые сценарии – где применить ИИ, чтобы было лучше, быстрее, дешевле;
— учим внедрять ИИ для управления продуктом от технического задания до запуска;
— делаешь реальные проекты прямо во время учёбы, а не ближе к диплому;
— диплом государственного образца МИФИ – одного из ведущих технических университетов страны.

Подробности и заявка здесь
👎1🔥1😁1
👩‍💻 Сегодня рассмотрим Channel<T> — безопасная асинхронная очередь задач в .NET

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

Что важно знать:

Работает без ручных блокировок и сложных синхронных вызовов.

Позволяет автоматически замедлять отправку при перегрузке памяти.

Обеспечивает плавную передачу данных между параллельными задачами.


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

C# Ready | #гайд
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥95👍3🤝1
2🔥2👍1🤝1
Понятный разбор того, как на самом деле работает async/await в C#!

В этой статье:
• Чем асинхронность отличается от запуска работы в отдельном потоке
• Когда await освобождает поток, а когда выполнение продолжается синхронно
• Как компилятор превращает асинхронный метод в машину состояний

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


➡️ C# Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
👍74🔥3