Библиотека шарписта | C#, F#, .NET, ASP.NET
21.7K subscribers
2.9K photos
46 videos
91 files
5.37K links
Все самое полезное для C#-разработчика в одном канале.

Наши курсы: https://clc.to/y3LDtw

По рекламе: @tproger_sales_bot

Для обратной связи: @proglibrary_feeedback_bot

РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead
Download Telegram
🚀 .NET 11 вышел в Release Candidate 1

8 сентября Microsoft выпустила первый RC .NET 11. У него уже есть Go-Live Support, поэтому сборку можно использовать в production — хотя для критичных систем разумнее дождаться финального релиза.

Что главное:

→ C# 15 стал default для .NET 11 — union types и closed hierarchies больше не preview;

→ runtime получил новые возможности для диагностики и оптимизации, включая crash reporting на Unix и аппаратное ускорение System.Half;

→ обновились SDK, MSBuild, NuGet, ASP.NET Core, MAUI и WinForms.


🌞 Финальный .NET 11 запланирован на 10 ноября и будет STS-релизом.

А 10 ноября заканчивается поддержка .NET 8 и .NET 9. Для них уже вышли сентябрьские security updates: 8.0.31, 9.0.20 и 10.0.12.

📍 Навигация: ВакансииЗадачиСобесы

🐸Библиотека шарписта

#async_news
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11😢2
✏️ Async/Await в C# — шпаргалка

➡️ Что такое Task

Task — это обещание, что какое-то событие произойдёт в будущем. Не результат, а именно обещание.

Task<T> — то же самое, но с результатом типа T. Когда задача завершится, значение станет доступно.

Задача считается завершённой, когда событие произошло или значение получено. Проверить это можно через IsCompleted или Status.

➡️ Как дождаться результата

Правильно — асинхронно:

• await task — отпускает поток, пока задача не завершится. Поток свободен, приложение не зависает.

• ContinueWith(action) — задача сама вызовет ваш колбэк, когда завершится. Полезно, если нужно выстроить цепочку без await.

Неправильно — синхронно:

• task.Wait() и task.Result блокируют текущий поток до завершения задачи. Это неэффективно, ведь поток простаивает и опасно: риск дедлока в UI и ASP.NET-контекстах.

Единственное исключение: вызывать Wait или Result на уже завершённой задаче безопасно и дёшево — результат уже есть, блокировки не будет.

➡️ Что делает async

async — это флаг для компилятора: «в этом методе может встретиться await, подготовь конечный автомат». Не более того.

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

async не запускает код в фоновом потоке. Если нужен фоновый поток — используйте Task.Run.

➡️ Что делает await

await — точка, в которой метод «разрезается» на до и после. Если задача ещё не завершена, управление возвращается вызывающему коду. Когда задача завершится — выполнение продолжится с того же места.

Без await ключевое слово async ничего не делает.

➡️ Частые ошибки

Вызов .Result или .Wait() в UI-потоке — дедлок. UI-поток заблокирован ожиданием, а задача не может завершиться, потому что ей нужен тот же UI-поток.

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

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

async без await — компилятор предупредит, и правильно сделает. Метод синхронный, а обёртка в Task создаёт ложные ожидания у вызывающего кода.

📍 Навигация: ВакансииЗадачиСобесы

🐸Библиотека шарписта

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
19👍4🥱1
🌞 Готовим вебинар про AI в разработке и хотим сделать его максимально полезным

Что реально хочется разобрать? Где чаще всего застреваете? Что пробовали, но так и не получилось нормально внедрить?


🤩 Пишите вопросы в комментариях — самые залайканные разберём на вебинаре в первую очередь.

Задавайте всё, что давно хотелось спросить 📍

📍 Навигация: ВакансииЗадачиСобесы

🐸Библиотека шарписта
Please open Telegram to view this post
VIEW IN TELEGRAM
4
This media is not supported in your browser
VIEW IN TELEGRAM
🌸 Вселенная намекает: пора уже начать этот курс

С 14 сентября цены в Proglib Academy вырастут на 20% 👀

Так что если курс давно ждёт своего часа — лучше не откладывать ещё на месяц 😏

📍 Выбрать курс
Please open Telegram to view this post
VIEW IN TELEGRAM
2
🧠 When и Unless для умных проверок

В FluentValidation условная валидация запускает правила только при нужных условиях. When и Unless экономят циклы и делают валидаторы читаемыми.

• When = «проверить, если условие верно»
• Unless = «проверить, если условие НЕ верно»

Пример:


RuleFor(x => x.ShippingAddress)
.NotEmpty()
.When(x => x.DeliveryMethod == "Express");

RuleFor(x => x.CreditCard)
.NotEmpty()
.Unless(x => x.PaymentMethod == "PayPal");


When проверяет условие перед правилом. Express доставка требует адрес, PayPal не требует карту. Логика в одном месте без if-else в контроллере.

📍 Навигация: ВакансииЗадачиСобесы

🐸Библиотека шарписта

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
3
С днем программиста, коллеги!

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

И конечно, пусть в жизни будет больше приятных сюрпризов — один из них мы уже подготовили. Скорее переходите по ссылке, трясите коробку и забирайте свой подарок ко Дню программиста: https://tprg.ru/YtJ2
🥰159🎉4👍1
🧩 Union types появились в ASP.NET Core на .NET 11

В C# 15 можно описать тип с несколькими допустимыми вариантами:


public union IntOrString(int, string);


Такой endpoint может вернуть либо число, либо строку:


app.MapGet("/max-unavailable", () => new IntOrString(2));


JSON останется обычным:


2
или:
"25%"


Без $type и дополнительных обёрток.

Главный плюс — компилятор проверяет, что switch обработал все варианты union.

Поддерживается в Minimal APIs, MVC, SignalR, Blazor и OpenAPI.

📍 Навигация: ВакансииЗадачиСобесы

🐸Библиотека шарписта

#async_news
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥203
😭 Как не потратить недельный лимит AI-кодинга за три дня?

Разберём на вебинаре, как тратить меньше на AI-агентов — без потери качества кода.

🔘 Поговорим о том:

— когда дорогая модель действительно нужна, а когда хватит дешёвой;
— сколько стоит один прогон и куда уходят токены;
— какие задачи можно отдавать субагентам;
— как настроить маршрутизацию моделей;
— что проверять в AI-коде перед merge.

✏️ Покажем всё на конкретных цифрах и вживую: сравним расходы до и после.

⬇️ 17 сентября, 19:00 МСК
⬇️ 1,5 часа · бесплатно
⬇️ Арсений Харланов и Олег Лайок

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

🔗 Зарегистрироваться на вебинар⁠
Please open Telegram to view this post
VIEW IN TELEGRAM
😁4🥱2🔥1
🧑‍💻 Забытый await: от race condition до DoS-атаки

В C# ключевое слово async — это инструкция компилятору превратить метод в state machine. await отмечает точку логической приостановки. Всё просто: выполнение не должно продолжаться, пока результат не существует.

При await весь код выполняется синхронно, пока не достигнет I/O или функции, возвращающей Task. Если Task не завершён, происходит раскрутка кадра стека, и поскольку обрамляющие методы приостановлены до самого верха, поток может быть освобождён в пул потоков.

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

Если забыли await:


var task = GetDataAsync();
// забыли await
Use(task);


Это режим «запустил и забыл» (fire-and-forget). Последствия:

• выполнение продолжается немедленно
• зависимость не обеспечивается
• исключения выходят за пределы логического стека вызовов

Что может произойти с приложением

⚠️ Забытый await может привести к классическому состоянию гонки: код продолжает выполнение до завершения критической операции, например, проверки прав доступа, открывая окно для эксплуатации.

Атакующий может успеть получить доступ к данным между моментом начала проверки и её завершением.

⚠️ Когда исключения выходят за пределы логического стека вызовов, они могут быть проглочены без логирования. Это маскирует неудачные попытки аутентификации, SQL-инъекции или другие атаки.

⚠️ Истощение пула потоков как вектор DoS-атаки. При высокой нагрузке неправильное использование async/await приводит к истощению пула потоков. Злоумышленник может намеренно генерировать запросы, эксплуатирующие блокирующие операции.

📍 Навигация: ВакансииЗадачиСобесы

🐸Библиотека шарписта

#il_люминатор
Please open Telegram to view this post
VIEW IN TELEGRAM
7👍4😁2🥱2
🧠 Почему .NET-под съедает всю память?

kubectl top pod показывает 1 ГБ, а managed heap занимает всего 300 МБ. Куда делись остальные 700?

Память .NET-процесса — это не только GC:

— managed heap;
— JIT и загруженные сборки;
— стеки потоков;
— native-библиотеки;
— буферы сокетов;
— runtime и TLS.


Поэтому одного GCHeapHardLimitPercent недостаточно: он ограничивает только managed heap.

🔴 Что проверить:


kubectl top pod
dotnet-counters monitor -p <pid> System.Runtime
dotnet-gcdump collect -p <pid>
dotnet-dump collect -p <pid>


🔴 И ещё несколько практических моментов:

→ не выставляй всем подам одинаковые memory limits;
→ проверь AsNoTracking() и проекции в EF Core;
→ ищи .Result, .Wait() и блокирующий I/O;
→ тестируй GC под реальным memory limit контейнера.

🔗 Источник

📍 Навигация: ВакансииЗадачиСобесы

🐸Библиотека шарписта

#il_люминатор
Please open Telegram to view this post
VIEW IN TELEGRAM
1
🦆 Duck typing в C# — почти как в TypeScript

В TypeScript достаточно, чтобы у объекта был нужный метод:


function foo(a: { Do(): void }) {
a.Do();
}


🔜 В C# так напрямую нельзя:


class A
{
public void Do() => Console.WriteLine("A.Do");
}

class B
{
public void Do() => Console.WriteLine("B.Do");
}


🔜 У A и B нет общего интерфейса. Но хочется вызвать:


Foo(new A());
Foo(new B());


И здесь на сцену выходят interceptors — экспериментальная возможность компилятора C#.

🌞 Идея:


[DuckShape]
public interface IDoable
{
void Do();
}

public static partial class Ops
{
[DuckTyped]
public static void Foo(IDoable value)
=> value.Do();
}


📍 Source generator создаёт адаптер:


internal readonly struct ShapeAdapter_IDoable_A : IDoable
{
private readonly A _value;

public ShapeAdapter_IDoable_A(A value)
=> _value = value;

public void Do() => _value.Do();
}


А interceptor подменяет вызов и оборачивает A или B в подходящий адаптер.

🔴 В итоге:


Ops.Foo(new A()); // A.Do
Ops.Foo(new B()); // B.Do


Работает и с properties — например, можно описать INameable с Name { get; set; }, а затем передать обычный Person, не меняя его код.

⚠️ Но это скорее интересный PoC, чем готовая замена интерфейсам:

— interceptors остаются экспериментальной возможностью;
— нужен source generator;
— есть ограничения и не покрытые edge cases;
— появляется дополнительная магия на этапе компиляции.

🔗 Источник

📍 Навигация: ВакансииЗадачиСобесы

🐸Библиотека шарписта

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥42👍2
🧩 Middleware в ASP.NET Core: 3 ловушки

Middleware — звено HTTP pipeline:


app.Use(async (context, next) =>
{
Console.WriteLine("Request");

await next(context);

Console.WriteLine("Response");
});



1️⃣ Забыл next() — остановил pipeline


await _next(context);


Если его не вызвать, middleware ниже и endpoint не выполнятся.

2️⃣ Scoped-сервис не стоит инжектить в конструктор

Middleware переиспользуется между запросами, поэтому Scoped лучше получать в InvokeAsync:


public async Task InvokeAsync(
HttpContext context,
IMyScopedService service)
{
await _next(context);
}


3️⃣ После начала ответа менять его уже нельзя


await _next(context);

context.Response.StatusCode = 503; // 💥



Если response уже отправляется, будет InvalidOperationException.

💡 Для действий до отправки используйте Response.OnStarting().

И ещё: не передавайте scoped-сервис в Task.Run после завершения запроса — его scope уже мог быть уничтожен. Для фоновой работы создавайте новый scope или используйте BackgroundService 🧠

🔗 Источник

📍 Навигация: ВакансииЗадачиСобесы

🐸Библиотека шарписта

#il_люминатор
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
💪 Разминка перед трудовыми буднями

Что произойдёт?

❤️ — список станет [1, 3]
🔥 — InvalidOperationException
👍 — цикл пропустит 2

Ответ спрячем здесь:

🔥 InvalidOperationException

foreach использует List<T>.Enumerator. После Remove() коллекция изменяется, перечислитель обнаруживает изменение при следующем MoveNext() и выбрасывает исключение.


📍 Навигация: ВакансииЗадачиСобесы

🐸Библиотека шарписта

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥462👍1