TGViewer
Channel Public Channel
Библиотека шарписта | C#, F#, .NET, ASP.NET

Библиотека шарписта | C#, F#, .NET, ASP.NET

@csharpproglib

Все самое полезное для C#-разработчика в одном канале.

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

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

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

РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead
Subscribers
21.7K
Photos
2.9K
Videos
46
Links
5.4K
Recent Posts 20 shown
Post #7273 1.3K
💪 Разминка перед трудовыми буднями

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

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

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

🔥 InvalidOperationException

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


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

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

#dotnet_challenge
  • 🔥 45
  • ❤ 2
  • 👍 1
Post #7272 1.82K
🧩 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_люминатор
  • 👍 7
Post #7270 2.27K
🦆 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
  • 🔥 4
  • ❤ 2
  • 👍 2
Post #7269 2.56K
🧠 Почему .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_люминатор
  • ❤ 1
Post #7268 2.7K
🧑‍💻 Забытый 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_люминатор
  • ❤ 7
  • 👍 4
  • 😁 2
  • 🥱 2
Post #7267 2.61K
😭 Как не потратить недельный лимит AI-кодинга за три дня?

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

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

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

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

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

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

🔗 Зарегистрироваться на вебинар⁠
  • 😁 4
  • 🥱 2
  • 🔥 1
Post #7266 2.91K
🧩 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
  • ❤‍🔥 20
  • ❤ 3
Post #7264 3.08K
С днем программиста, коллеги!

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

И конечно, пусть в жизни будет больше приятных сюрпризов — один из них мы уже подготовили. Скорее переходите по ссылке, трясите коробку и забирайте свой подарок ко Дню программиста: https://tprg.ru/YtJ2
  • 🥰 15
  • ❤ 9
  • 🎉 4
  • 👍 1
Post #7263 2.95K
🧠 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
  • ❤ 3
Post #7262 2.65K
🌸 Вселенная намекает: пора уже начать этот курс

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

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

📍 Выбрать курс
  • ❤ 2
Post #7260 2.83K
🌞 Готовим вебинар про AI в разработке и хотим сделать его максимально полезным

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


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

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

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

🐸Библиотека шарписта
  • ❤ 4
Post #7258 3.36K
✏️ 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
  • ❤ 19
  • 👍 4
  • 🥱 1
Post #7257 3.65K
🚀 .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
  • 🔥 11
  • 😢 2
Post #7256 3.77K
💥 Куда исчезает метод после JIT-компиляции?

В C# мы пишем:


int Double(int x) => x * 2;

var result = Double(21);


Но JIT может решить, что отдельный вызов здесь вообще не нужен.

При inlining тело метода встраивается непосредственно в вызывающий код:

🔴 До:


call Double

x * 2


🔴 После:


21 * 2


Зачем? Меньше накладных расходов на вызов метода, а главное — JIT получает больше кода для последующих оптимизаций. Но inline не означает «метод маленький → обязательно встроить».

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

📍 А атрибут:


[MethodImpl(MethodImplOptions.AggressiveInlining)]

— это подсказка JIT, а не приказ.

И наоборот, иногда большой метод всё-таки может быть встроен, если JIT считает это выгодным.

Вот почему производительность C# нельзя оценивать только по исходному коду: между C# и CPU есть ещё один слой — JIT и его оптимизатор.

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

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

#il_люминатор
  • 🔥 8
  • ❤‍🔥 3
Post #7255 3.83K
🧪 MSTest 4.4 теперь поддерживает Native AOT

Тесты тоже должны проверять то, что мы отправляем в production. Native AOT означает trimming, ограничения reflection и отсутствие runtime code generation. Обычный managed-тест может этого не показать.

В MSTest 4.4 появился source generation для тестов — test discovery и запуск можно выполнять без зависимости от runtime reflection.


<PublishAot>true</PublishAot>


В итоге можно прогнать тесты в тех же AOT-условиях, в которых будет работать приложение.

Особенно полезно для проектов, где Native AOT — часть production-сборки.

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

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

#async_news
  • ❤ 7
Post #7254 3.75K
💡 FrozenDictionary. Когда словарь больше не должен меняться

Если коллекция после создания больше не изменяется, обычный Dictionary<TKey, TValue> не всегда лучший вариант.

В .NET 8 появились FrozenDictionary и FrozenSet — специализированные неизменяемые коллекции для сценариев, где данные сначала собираются, а потом много раз читаются.


var users = new Dictionary<int, string>
{
[1] = "Ada",
[2] = "Linus",
[3] = "Grace"
};

var frozenUsers = users.ToFrozenDictionary();


После создания frozenUsers нельзя изменить. Зато структура оптимизируется именно под быстрый поиск.

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

FrozenDictionary не означает «быстрее любого Dictionary». Создание такой коллекции дороже, поэтому выигрыш появляется именно там, где чтений много, а изменений нет.

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

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

#sharp_view
  • 👍 10
  • ❤ 4
Post #7253 4.35K
👨‍💻 string в C# — не просто текст

string — это ссылочный тип с особой поддержкой рантайма. Внутри он хранит непрерывный блок UTF-16 кодовых единиц.

Отсюда первый сюрприз:


string s = "😊";
Console.WriteLine(s.Length); // 2, не 1


Length считает не символы, а UTF-16 кодовые единицы. Эмодзи и многие Unicode-символы занимают две единицы — суррогатную пару.

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

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

#sharp_view
  • ❤ 12
  • 🥱 6
  • 😢 1
Post #7252 4.31K
⚙️ nameof теперь понимает несвязанные обобщения

Удобство и гибкость метапрограммирования — теперь nameof работает для обобщений без аргументов.

Благодаря новой поддержке можно получить имена обобщенных типов без указания параметров:

Console.WriteLine(nameof(List<>));  // Выведет "List"


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

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

#sharp_view
  • 🔥 15
Older posts →

About this channel

How can I read @csharpproglib without a Telegram account?
TGViewer shows the public web preview Telegram publishes for Библиотека шарписта | C#, F#, .NET, ASP.NET: recent posts, photos, videos and the subscriber count, with no app, login or account.
How many subscribers does Библиотека шарписта | C#, F#, .NET, ASP.NET have?
Библиотека шарписта | C#, F#, .NET, ASP.NET (@csharpproglib) has 21.7K subscribers on Telegram, refreshed roughly every 30 minutes.
Does Библиотека шарписта | C#, F#, .NET, ASP.NET know I viewed it here?
No. Public channel previews carry no viewer identity, and TGViewer has no accounts or tracking of what you look up.
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →