Библиотека шарписта | C#, F#, .NET, ASP.NET
22.2K subscribers
2.68K photos
41 videos
85 files
5K links
Все самое полезное для C#-разработчика в одном канале.

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

Учиться у нас: https://proglib.io/w/b60af5a4

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

РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead
Download Telegram
👀 YAGNI в реальной жизни

YAGNI (You Aren't Gonna Need It) — принцип из разработки: не делайте то, что может пригодиться когда-нибудь. Работает не только в коде.

Не покупайте инструмент на всякий случай. Нужна дрель — возьмите в аренду или одолжите. Купите перфоратор — будет пылиться 10 лет.

Не записывайтесь на 5 курсов параллельно, «пройду потом» может не случится — вдруг смените род деятельности, к примеру. Закончите один, потом решайте нужен ли следующий.

💬 Бывало такое, что нарушали YAGNI в реальной жизни? Или может наоборот трезво оценили ситуацию и не купились? Интересно будет почитать в комментах 👇

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

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

#entry_point
Please open Telegram to view this post
VIEW IN TELEGRAM
💯223👍2
🔗 Идём в нативный мир

Иногда .NET-коду нужно выйти за пределы управляемого мира и напрямую поговорить с операционной системой, нативными библиотеками или COM-компонентами. Для этого существует Native Interop — набор механизмов, встроённых прямо в рантайм.

Зачем это вообще нужно

Три основных сценария: ОС предоставляет огромное количество API, которых нет в BCL, например, доступ к оборудованию, системные вызовы; интеграция с кодом на C/C++ или Java через JNI; и автоматизация Windows-приложений вроде Office через COM.

Platform Invoke — главный инструмент

Platform Invoke позволяет вызывать функции из нативных библиотек .dll / .so / .dylib. В .NET 7+ вместо старого [DllImport] рекомендуется использовать [LibraryImport]:
[LibraryImport("nativelib", EntryPoint = "to_lower",
StringMarshalling = StringMarshalling.Utf16)]
internal static partial string ToLower(string str);


LibraryImport запускает source-генератор, который формирует весь код маршалинга на этапе компиляции, а не в рантайме — это открывает возможность для Native AOT и инлайнинга P/Invoke-вызовов.

Маршалинг типов

Маршалинг необходим потому, что типы в управляемом и неуправляемом коде различаются. Например, в .NET строка одна, а в нативном коде их может быть множество: UTF-16, ANSI, UTF-8, null-terminated, ASCII и так далее.

Для управления маршалингом используются атрибуты [MarshalAs] и [StructLayout]. Для нативных структур нужно воспроизвести их в управляемом коде с точным совпадением порядка и размеров полей.

Blittable-типы — типы с одинаковым битовым представлением в managed и native коде. Они не требуют конвертации и просто закрепляются в памяти — используйте их везде, где возможно.

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

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥31
💡 Подборка вакансий для шарпистов

Senior разработчик C# — удалёнка

Middle/Middle+ C#/.NET Developer — тоже удалёнка

.NET-разработчик — от 250 000 ₽ и снова удалёнка

➡️ Еще больше топовых вакансий — в нашем канале C# Jobs

🐸 Библиотека шарписта
Please open Telegram to view this post
VIEW IN TELEGRAM
1
За год мы провели три потока курса по ИИ-агентам, а теперь запускаем масштабное обновление!

В новом, четвёртом потоке мы учли все пожелания студентов, добавили большой блок про AgentOps и сместили фокус с базовых концепций на суровый инжиниринг. Сделать простую цепочку на C
легко, а вот интегрировать агентов в корпоративный контур, чтобы они не галлюцинировали и не сливали бюджет в проде — задача со звёздочкой.

В программе:

— интеграции по стандарту MCP и мультиагентные паттерны;
— оркестрация в LangGraph: human-in-the-loop и runbook для отказов;
— продвинутый RAG для промышленной эксплуатации и парсинг сложных документов;
— контроль экономики агентов: маршрутизация и кеширование;
— развёртывание локальных опенсорс-моделей в закрытых контурах по 152-ФЗ.

В честь старта продаж действует спецпредложение: 3 курса по цене 1 (два дополнительных курса в подарок).

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

По промокоду Agent забирайте скидку 10 000 ₽ (89 000 ₽ вместо 99 000 ₽). Успейте занять место до 28 февраля!

👉 Присоединиться к четвёртому потоку и вывести агентов в прод
2
✏️ Оставить след в опенсорсе

goodfirstissue.dev собирает задачи с пометкой good first issue из популярных проектов — это реальные баги и небольшие фичи, которые мейнтейнеры специально отмечают как подходящие для новичков в проекте.

Контрибьют в open-source — это не только строчка в резюме. Это код-ревью от людей, которые написали библиотеки, которыми мы пользуемся, и понимание того, как устроены проекты изнутри.

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

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
🤖 GitHub Copilot Testing для .NET теперь в Visual Studio 2026

Microsoft официально выпустила инструмент для автоматической генерации юнит-тестов прямо в IDE. Больше не нужно писать тесты с нуля вручную.

Вы пишете в Copilot Chat @Test и описываете, что хотите протестировать. И Copilot сам:

— генерирует юнит-тесты
— собирает и запускает их
— находит упавшие тесты и пытается их починить
— повторяет, пока всё не стабилизируется
— показывает итоговый отчёт: покрытие до/после, что прошло, что упало

Что можно просить:
@Test покрой тестами мою бизнес-логику
@Test класс OrderService, целевое покрытие 80%
@Test напиши тесты для моих текущих изменений в git
@Test используй xUnit и FluentAssertions


Область охвата: метод, класс, файл, проект, весь solution или текущий git diff — на ваш выбор.

➡️ Блог Microsoft

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

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

#async_news
Please open Telegram to view this post
VIEW IN TELEGRAM
👍91🥱1
⚡️ .NET 10 Blazor: как выбрать render mode для реального проекта

Blazor даёт три модели выполнения. Это не стилистические различия — они определяют где живёт память, как работает сеть и во сколько обходится масштабирование.

Interactive Server

C# выполняется на сервере, браузер — тонкий клиент. Между ними — постоянный WebSocket: каждое UI-событие летит на сервер, обратно возвращается только diff DOM.

Каждая открытая вкладка создаёт circuit в памяти сервера. 1000 пользователей — ~300 МБ только на состояние, 20 000 — уже серьёзная инфраструктура.

Зато можно инжектить DbContext прямо в компонент, не нужен API-слой, скорость разработки максимальная. Подходит для внутренних инструментов с небольшой аудиторией.

Interactive WebAssembly

Браузер скачивает .NET runtime и сборки приложения, C# выполняется локально. UI-события не уходят в сеть — отклик мгновенный.

Сервер становится stateless: только API и статика.
Первая загрузка тяжелее — от 2 до 10+ МБ в зависимости от сборок. И главное правило: никаких секретов в WASM, IL декомпилируется.

Вся авторизация и бизнес-логика — только за API. Хорошо масштабируется, дёшево хостится через CDN.

Interactive Auto

Гибридный режим: первый визит работает как Server — мгновенный рендер без ожидания загрузки WASM. Параллельно браузер скачивает рантайм, и при следующем визите компонент уже выполняется на клиенте.

Сложность в том, что один и тот же компонент должен уметь работать в обоих контекстах. Прямой @inject AppDbContext сломается в браузере.

Решение — общий интерфейс с двумя реализациями: серверной и клиентской. DI сам подставит нужную.

Как выбирать:

— небольшая внутренняя аудитория, нужна скорость разработки → Server

— публичный SaaS, много пользователей, важна стоимость хостинга → WebAssembly

— публичное приложение, важен SEO и первый paint, но нужна SPA-производительность → Auto

— сложный продукт с разными модулями → комбинируйте режимы под каждый раздел

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

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
👍145
🔍 PVS-Studio 7.41

Вышел новый релиз статического анализатора PVS-Studio. Разбираем, что изменилось.

Улучшения для Unreal Engine

Исправлены ошибки в диагностическом правиле V557 при работе с контейнерами движка, а также проблема с парсингом спецификатора final в виртуальных функциях.

Taint-анализ в C#

Добавлена поддержка JSON-аннотаций для async-функций. Теперь можно передавать анализатору дополнительный контекст через JSON-файл для асинхронного кода.

Утилита pvs-fp-cleaner

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

Плагин IntelliJ IDEA

Добавлен экспорт отчётов в CSV, отображение относительных путей, исправлено торможение при открытии документации.

Новое правило для C#

V3230 — бессмысленное сравнение с typeof(Nullable)

➡️ Release Notes

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

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

#async_news
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
⚡️ Корректность в условиях конкурентности

Современный код на .NET редко выполняется изолированно.

Тревожный сигнал:
static List<Order> _orders = new();


List<T> не потокобезопасен — параллельная запись приведёт к повреждению данных или исключению.

Лучше:
static ConcurrentBag<Order> _orders = new();


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

Вопросы для ревью такого кода:

— Защищено ли общее состояние?
— Есть ли состояния гонки?
— Безопасен ли код при параллельном выполнении?
— Действительно ли асинхронные методы потокобезопасны?
— Нет ли скрытого изменяемого состояния в статических полях?
— Используются ли потокобезопасные коллекции там, где это нужно?

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

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱62
Что выведет код

Сделали сниппет кода на манер JavaScript, складываем число и строку. В C#, в отличие от JS, это операция предсказуемая и можно догадаться о результате.

➡️ Проверьте себя не запуская код

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

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

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
Последний шанс: 3 курса по цене 1 и запуск AI-агентов в продакшн

Дёргать API OpenAI из .NET-сервисов — весело, но энтерпрайзу нужна предсказуемость. Как интегрировать ИИ-агентов в корпоративную инфраструктуру, контролировать затраты и не нарушить 152-ФЗ?

В обновлённой программе фокус смещён на жёсткий инжиниринг и вывод мультиагентных систем в прод. Вы научитесь строить ReAct-циклы, работать с оркестраторами вроде LangGraph, внедрять продвинутый RAG, протоколы MCP и AgentOps. Все ключевые навыки в одном месте: измеримость систем, интеграция с легаси, human-in-the-loop и развёртывание LLM-решений в закрытых контурах.

Почему нельзя откладывать:

— масштабная акция «3 курса по цене 1» сгорит уже завтра;
— промокод Agent на скидку 10 000 рублей действует последние часы;
— сразу после оформления открываются материалы для подготовки — начать учиться можно прямо сейчас.

Забронировать место на курсе и забрать бонусы до 28 февраля
👨‍💻 string в C# — не просто текст

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

Отсюда первый сюрприз:
string s = "😊";
Console.WriteLine(s.Length); // 2, не 1


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

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

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
👍165🤔1
🌍 Сравнение строк и культура

Когда вы сравниваете строки в C#, результат зависит не только от содержимого, но и от того, как вы сравниваете. И здесь кроется целый класс багов, которые воспроизводятся только на машинах с определёнными региональными настройками.

Два режима сравнения:

Ordinal — побайтовое сравнение Unicode-значений. Быстрое, предсказуемое, не зависит от культуры.

CurrentCulture — сравнение по правилам текущей локали операционной системы. Медленнее, результат может отличаться на разных машинах.

Пример с немецким языком:
string a = "straße";  // немецкое "улица"
string b = "strasse"; // то же слово, другое написание

a.Equals(b, StringComparison.CurrentCultureIgnoreCase); // true на de-DE
a.Equals(b, StringComparison.CurrentCultureIgnoreCase); // false на en-US
a.Equals(b, StringComparison.OrdinalIgnoreCase); // false везде


Один и тот же код даёт разные результаты в зависимости от того, где запущен. На машине разработчика работает, на продакшен-сервере — нет.

Турецкая проблема:
// В турецкой локали (tr-TR):
"I".ToLower() == "ı" // не "i", а "ı" (без точки)
"i".ToUpper() == "İ" // не "I", а "İ" (с точкой)

// Поэтому:
string input = "FILE";
input.ToLower() == "file" // false на турецкой машине!


Именно из-за этого Microsoft SQL Server годами имел баги в коде, который работал везде, кроме турецких инсталляций.

Анализатор CA1307 в .NET предупреждает о вызовах сравнения без явного указания StringComparison. Включите его — он поймает большинство таких мест автоматически.

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

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

#il_люминатор
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🤔53
Энтерпрайз убивает драйв? Стань техническим кофаундером в EdTech-стартапе 🚀

Proglib App — платформа для обучения разработчиков (курсы, квизы, ИИ-агенты). MVP уже в проде, пользователи растут. Проекту нужен сильный инженер, готовый взять на себя роль технического лидера и строить продукт вместе с основателем.

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

🛠️ Стек (современный Fullstack):

TypeScript, React 18, Express 5, PostgreSQL, Drizzle ORM.

Почему это может быть интересно:

Никакой бюрократии: только код, продукт и архитектурные решения.
Инструменты: работа с ИИ-ассистентами (Claude Code, Cursor).
Рост: путь от MVP до масштабного сервиса в роли партнёра.

Ожидания:

• Крепкий бэкграунд в разработке и понимание архитектуры БД.
• Готовность работать с TS/React/Node.js.
• Автономность и продуктовое мышление.

Удалёнка, гибкий график, полная свобода в реализации идей.

Готов сменить привычный стек на роль кофаундера? Пиши о себе и кидай GitHub 👇

@proglibrary_feedback_bot
2👍1
📝 Логирование со строковой интерполяцией

Логирование c интерполяцией строк один из самых распространённых источников лишних аллокаций в .NET-приложениях.

Особенность в том, что код выглядит абсолютно нормально и работает правильно — просто дорого.

Что происходит с интерполяцией:
logger.LogInformation($"User {userId} logged in at {time}");


Компилятор разворачивает это примерно в:
logger.LogInformation(string.Format("User {0} logged in at {1}", userId, time));


Строка формируется до вызова метода. Если уровень логирования Information отключён, строка всё равно создаётся, занимает память и тут же выбрасывается сборщиком мусора.

Структурное логирование решает проблему:
logger.LogInformation("User {UserId} logged in at {Time}", userId, time);


Здесь строка — это шаблон. Аргументы передаются отдельно. Логгер сначала проверяет, активен ли уровень, и только потом форматирует сообщение. Если уровень выключен — аллокации нет вообще.

Бонус: структурное логирование позволяет индексировать поля в системах вроде Seq, Elasticsearch, Datadog — вы сможете искать по UserId как по полю, а не парсить текст.

Начиная с .NET 6 есть ещё лучший вариант через compile-time source generators:
// Генерирует оптимальный код на этапе компиляции:
[LoggerMessage(Level = LogLevel.Information, Message = "User {UserId} logged in at {Time}")]
partial void LogUserLogin(int userId, DateTime time);


Никаких аллокаций, никакого боксинга, максимальная производительность — и всё это без изменения читаемости кода.

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

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

#il_люминатор
Please open Telegram to view this post
VIEW IN TELEGRAM
👍216🤔1
🔄 Cake 6.0.0 вышел

Cake — это инструмент автоматизации сборки для .NET-проектов. Скрипты пишутся на C# с простым DSL, который покрывает компиляцию, тестирование, публикацию и всё, что обычно делают в CI/CD пайплайне.

Логирование теперь принимает интерполированные строки напрямую. Сообщение формируется только если текущий уровень логирования активен:
Information($"Building {project} v{version}");

Verbose(log => log($"Processing {items.Count} items in {stopwatch.ElapsedMilliseconds} ms"));


Cake.Sdk получил поддержку in-process NuGet клиента. Теперь через #tool и InstallTool можно устанавливать любые NuGet пакеты прямо в инструменты.

Добавлена поддержка .slnx файлов. DotNetTest и парсинг решений теперь распознают XML-формат solution файлов, а автоопределение типа пути включает .slnx.

Из других изменений: NuGetPack теперь поддерживает поле ReadMe для readme пакета, в AssemblyInfo creator можно добавлять несколько экземпляров одного атрибута, in-process NuGet restore заработал с аутентификацией через приватные фиды.

Есть breaking change для GitLab CI — поля CI_PIPELINE_ID и CI_BUILD_ID сменили тип с int на long, так как на gitlab.com идентификаторы давно вышли за пределы 32 бит.

➡️ Release Notes

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

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

#async_news
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6❤‍🔥22
💻 Утечки памяти в .NET

В .NET утечки памяти почти никогда не связаны с ручным управлением указателями. Они появляются из-за ошибок в управлении временем жизни объектов.

Главный инструмент .NET для освобождения ресурсов — интерфейс IDisposable и его асинхронный вариант IAsyncDisposable. Если объект реализует один из них, значит он держит что-то важное: файловый дескриптор, сетевое соединение, неуправляемую память.

Без using объект останется жить до следующего прохода GC, а ресурс под ним — ещё дольше:
// Утечка: поток не закроется при исключении
var stream = new FileStream(path, FileMode.Open);

// Правильно: using гарантирует закрытие даже при исключении
using var stream = new FileStream(path, FileMode.Open);


Для асинхронных ресурсов — await using:
await using var resource = GetAsyncDisposable();


Что проверить в коде

Потоки. Каждый Stream, StreamReader, StreamWriter должен быть обёрнут в using. Без этого файловые дескрипторы накапливаются.

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

Крупные аллокации. Массивы, буферы, большие строки — если они создаются в цикле, это быстро давит на GC. Здесь помогает ArrayPool<T> или System.Buffers.

var pool = ArrayPool<byte>.Shared;
byte[] buffer = pool.Rent(4096);
try
{
// работа с буфером
}
finally
{
pool.Return(buffer);
}


Object Pooling. Если объекты дорогие в создании и используются часто — ObjectPool<T> из Microsoft.Extensions.ObjectPool снижает нагрузку на аллокатор.

Простое правило: если тип реализует IDisposable, оборачиваем его в using. Остальное — профилировщик покажет.

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

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

#il_люминатор
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8👍2
👨‍💻 Генерируйте curl прямо из кода

HttpClient.CurlDelegatingHandler — это обработчик в пайплайне HttpClient, который перехватывает запрос и возвращает готовую curl-команду в заголовке ответа. Никакой дополнительной логики писать не нужно.

Поддерживаются GET, POST, PUT и DELETE.

Как подключить:
dotnet add package HttpClient.CurlDelegatingHandler --version 1.0.0-alpha.1


Как использовать

Передаёте CurlDelegatingHandler при создании клиента. Чтобы запрос не ушёл в сеть, добавляете заголовок CanSend: False. Curl-команда придёт обратно в заголовке outputCurl.

using System.Text;
using CurlGenerator;

string url = "https://jsonplaceholder.typicode.com/posts";
string jsonPayload = @"{""title"": ""New Post"", ""body"": ""This is the body"", ""userId"": 1}";
var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");

var httpClient = new HttpClient(new CurlDelegatingHandler());
httpClient.DefaultRequestHeaders.Add(Settings.CanSend, "False");

var result = await httpClient.PostAsync(url, content);
string outputCurl = result.Headers.GetValues(Settings.OutputCurl).FirstOrDefault();

Console.WriteLine(outputCurl);


Вывод:
curl -X POST 'https://jsonplaceholder.typicode.com/posts' -H 'Content-Type: application/json' ...


DelegatingHandler встраивается в цепочку обработчиков HttpClient. Вместо того чтобы отправлять запрос по сети, он его перехватывает, строит из него curl-строку и возвращает её в заголовке ответа. Вся логика изолирована в одном месте.

➡️ Затестить пакет

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

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
👍122🌚1
🤔 Спам тимлидам, фейковые офферы и приукрашенное резюме

IT-рынок 2026 года — это не конкурс честных и талантливых. Компании говорят об экологичной культуре, а сами гостят после четырёх этапов отбора.

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

➡️ Узнать приёмы тех, кто смог

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

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
😢4