23284
Все самое полезное для C#-разработчика в одном канале. По рекламе: @proglib_adv Учиться у нас: https://proglib.io/w/b60af5a4 Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead
🖥 Первый дайджест весны
Прошла первая неделя весны и мы снова собрали для вас то, что могло уйти из вашего инфополя.
— Cake 6.0.0 вышел
— Спам тимлидам, фейковые офферы и приукрашенное резюме
— Merge conflict для календаря
— NuGet стал удобнее
— Noundry готова к бою
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#async_news
👨💻 Кэширование в три слоя — спасение базы данных
База данных имеет лимит количества запросов в секунду, который она может обработать. При миллионах запросов в час этот лимит будет достигнут независимо от того, насколько хорошо написан код. Решение одно: кэшировать агрессивно.
Неправильный подход это кэшировать все и везде без логики. Правильный подход это иметь стратегию кэширования с разными слоями.
Первый слой: память приложения
MemoryCache в .NET работает очень быстро, потому что данные лежат в памяти одного процесса. Здесь кэшируются часто запрашиваемые данные с коротким временем жизни. Профили пользователей, настройки, статические справочники. TTL может быть 30 секунд или минута.
Второй слой: распределенный кэш
Redis или Memcached. Когда приложение запущено на нескольких контейнерах, они должны видеть одни и те же данные. Если один контейнер кэшировал профиль пользователя, остальные должны получить его без запроса в БД.
Третий слой: кэширование ответов
Некоторые API ответы не зависят от пользователя и могут быть закэшированы целиком. Если GET /api/countries возвращает список стран, это можно кэшировать на час, потому что страны не меняются часто.
На практике такая архитектура может снизить нагрузку на базу данных на 80 процентов. Просто потому, что большинство запросов идут в кэш, а не в БД.
Ключ в том, чтобы знать, какие данные и как долго кэшировать. Не нужно хранить в кэше пользовательские данные, которые меняются каждую секунду. Нужно кэшировать данные, которые стабильны и часто запрашиваются.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#il_люминатор
📎 JsonSerializerOptions в каждом запросе это бомба замедленного действия
Вы оптимизировали базу данных. Ничего не изменилось. Оптимизировали сетевые вызовы. Всё ещё медленно.
Оказалось, приложение создаёт новый JsonSerializerOptions в каждом запросе. Это уничтожает встроенный кеш метаданных System.Text.Json и превращает JSON сериализацию в дорогую операцию, которая повторяется сотни раз в секунду под нагрузкой.
Почему это так дорогоJsonSerializerOptions это не просто настройки. Это место, где System.Text.Json хранит кэшированные метаданные о том, как сериализовать и десериализовать типы.
Каждый новый экземпляр JsonSerializerOptions начинает с пустого кеша. System.Text.Json должна заново анализировать тип, строить информацию о сериализации, кешировать её. Потом запрос закончился и всё выбросилось.
Следующий запрос приходит. Новый экземпляр. Пустой кеш снова. Всё сначала.
Microsoft так серьёзно относится к этому, что добавили анализатор CA1869, который явно предупреждает: не создавайте JsonSerializerOptions локально в горячих путях.
Ошибка выглядит безобидно:
string ToJson(object value)
{
var options = new JsonSerializerOptions(JsonSerializerDefaults.Web)
{
WriteIndented = false
};
return JsonSerializer.Serialize(value, options);
}
public static class JsonDefaults
{
public static readonly JsonSerializerOptions Web = new(JsonSerializerDefaults.Web)
{
WriteIndented = false,
Converters = { new JsonStringEnumConverter() }
};
}
Используем кеш, никаких затрат
return JsonSerializer.Serialize(payload, JsonDefaults.Web);
👨💻 Noundry готова к бою
Noundry это набор инструментов и библиотек для .NET разработки. В состав входит Tuxedo, Tailbreeze, Assertive, Authnz, Engine, AI Gateway и другие компоненты.
Разработчик годами решал одни и те же задачи за корпоративными файрволами. Классическое энтерпрайз консультирование: сложные системы, высокие ставки, миллионы транзакций. Код был хороший, но никто не видел. Результат работы жил за файрволом.
Теперь он решил поделиться тем, что наработал за два десятилетия. Выложил в публичное и начал строить сообщество вокруг этого.
➡️ Веб-сайт
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#async_news
👍 На курсе по контролируемой разработке AI-агентов мы будем разбирать ровно то, о чём говорит Владислав в голосовом, но уже в формате системной практики.
📅 Старт курса — 20 апреля.
Если хотите разобраться, как строить управляемые агентные системы:
➡️ Присоединяйтесь.
P.S. С первого занятия будет практика: код и разбор реальных ошибок, а не только теория.
⚙️ Базовый класс в C#: когда чистая архитектура становится проблемой
Всё начинается разумно. В нескольких сервисах повторяется одна логика — контекст БД, аудит, логирование. Выносишь в базовый класс. Код короче, дублирования нет.
Проходит полгода. Простой юнит-тест поднимает глобальную шину событий и запускает рефлексию. Никто не просил. Просто создали экземпляр репозитория.
Что происходит в конструкторе:
public abstract class RepositoryBase<TEntity>
{
protected RepositoryBase(DbContext context)
{
Context = context;
ApplyEntityConfiguration(); // рефлексия
SubscribeToAuditEvents(); // подписка на события
}
}
base() — и получил в нагрузку поведение, которое не запрашивал. Это невидимая связанность: поведение определяется не сигнатурой, а тем, что спрятано в цепочке наследования.RepositoryBase → MongoBase → AuditableBase → ProductRepository. Четыре уровня. Поведение на каждом. Ничего не видно на месте вызова.public class AuditingRepository : IProductRepository
{
private readonly IProductRepository _inner;
private readonly IAuditService _audit;
public async Task<Product> GetByIdAsync(Guid id)
{
await _audit.LogAccessAsync(id);
return await _inner.GetByIdAsync(id);
}
}
Program.cs, а не в базовом классе, который загружается неизвестно когда.
🛠 Жизни зависимостей в ASP.NET
Одна из самых частых причин непредсказуемого поведения приложений на ASP.NET Core — неправильно выбранное время жизни сервиса. Проблема тихая: приложение запускается, тесты проходят, а в продакшне начинается что-то странное.
Три режима, которые нужно знать
В ASP.NET у каждого сервиса есть время жизни экземпляра.
Transient. Новый экземпляр создаётся каждый раз, когда сервис запрашивается из контейнера. Подходит для лёгких, stateless-сервисов без общего состояния.
Scoped. Один экземпляр на HTTP-запрос. Все зависимости внутри одного запроса получают один и тот же объект. Это стандартный выбор для большинства сервисов в веб-приложениях.
Singleton. Один экземпляр на всё время жизни приложения. Создаётся один раз и переиспользуется во всех запросах.
Где ломается
Самая распространённая ошибка — инжектировать Scoped-сервис в синглтон. Выглядит невинно, но это называется captive dependency, и ASP.NET даже выбросит исключение при старте, если включена валидация.
// Так делать не надо
public class MySingleton
{
private readonly IScopedService _scoped;
public MySingleton(IScopedService scoped) // Проблема здесь
{
_scoped = scoped;
}
}
IServiceScopeFactory:public class MySingleton
{
private readonly IServiceScopeFactory _scopeFactory;
public MySingleton(IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory;
}
public void DoWork()
{
using var scope = _scopeFactory.CreateScope();
var scoped = scope.ServiceProvider.GetRequiredService<IScopedService>();
scoped.Execute();
}
}
builder.Host.UseDefaultServiceProvider(options =>
{
options.ValidateScopes = true;
options.ValidateOnBuild = true;
});
🗓 Merge conflict, но для календаря
В git есть автоматический резолв конфликтов. Теперь такое есть и для встреч — Microsoft Copilot в Outlook и Teams умеет сам переносить встречи, если в расписании возник конфликт.
Работает для личных встреч и 1:1. Групповые звонки, встречи длиннее 5 часов и повторяющиеся реже раза в месяц — пока не поддерживаются. Но для большинства рабочих 1:1 — уже удобно.
➡️ Источник
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#async_news
🤔 Спам тимлидам, фейковые офферы и приукрашенное резюме
IT-рынок 2026 года — это не конкурс честных и талантливых. Компании говорят об экологичной культуре, а сами гостят после четырёх этапов отбора.
На одну вакансию — тысяча откликов за сутки. В таких условиях выигрывают не самые опытные, а самые адаптивные.
➡️ Узнать приёмы тех, кто смог
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#sharp_view
💻 Утечки памяти в .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 var resource = GetAsyncDisposable();
Stream, StreamReader, StreamWriter должен быть обёрнут в using. Без этого файловые дескрипторы накапливаются.HttpClient. Один из самых частых источников проблем. Его нельзя создавать на каждый запрос, так как это исчерпывает пул сокетов.ArrayPool<T> или System.Buffers.var pool = ArrayPool<byte>.Shared;
byte[] buffer = pool.Rent(4096);
try
{
// работа с буфером
}
finally
{
pool.Return(buffer);
}
ObjectPool<T> из Microsoft.Extensions.ObjectPool снижает нагрузку на аллокатор.
📝 Логирование со строковой интерполяцией
Логирование 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);// Генерирует оптимальный код на этапе компиляции:
[LoggerMessage(Level = LogLevel.Information, Message = "User {UserId} logged in at {Time}")]
partial void LogUserLogin(int userId, DateTime time);
📰 Дайджест недели
Один пост — лучшее недели.
— TDD в больших проектах
— GitHub Copilot Testing в Visual Studio 2026
— Как выбрать render mode в Blazor
— PVS-Studio 7.41
— Один интерфейс — любой канал для уведомлений
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#async_news
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#garbage_collector
Последний шанс: 3 курса по цене 1 и запуск AI-агентов в продакшн
Дёргать API OpenAI из .NET-сервисов — весело, но энтерпрайзу нужна предсказуемость. Как интегрировать ИИ-агентов в корпоративную инфраструктуру, контролировать затраты и не нарушить 152-ФЗ?
В обновлённой программе фокус смещён на жёсткий инжиниринг и вывод мультиагентных систем в прод. Вы научитесь строить ReAct-циклы, работать с оркестраторами вроде LangGraph, внедрять продвинутый RAG, протоколы MCP и AgentOps. Все ключевые навыки в одном месте: измеримость систем, интеграция с легаси, human-in-the-loop и развёртывание LLM-решений в закрытых контурах.
Почему нельзя откладывать:
— масштабная акция «3 курса по цене 1» сгорит уже завтра;
— промокод Agent на скидку 10 000 рублей действует последние часы;
— сразу после оформления открываются материалы для подготовки — начать учиться можно прямо сейчас.
Забронировать место на курсе и забрать бонусы до 28 февраля
⚡️ Корректность в условиях конкурентности
Современный код на .NET редко выполняется изолированно.
Тревожный сигнал:
static List<Order> _orders = new();
List<T> не потокобезопасен — параллельная запись приведёт к повреждению данных или исключению.static ConcurrentBag<Order> _orders = new();
💥 Открытый вебинар | ИИ-агенты в продакшене: от хайпа к деньгам
Агенты уже везде. Но мало кто признаётся, сколько денег сжёг на бесконечных циклах, галлюцинациях в RAG и отсутствии мониторинга.
Полина Полунина, руководитель AI-направления Альфа-Банка, расскажет честно:
▪️ Чем агент отличается от «просто GPT с промптом» и когда бизнесу достаточно обычного LLM
▪️ 3 реальных кейса из корпоративной среды: что взлетело, а что нет
▪️ Live-демо работающего агента
▪️ ТОП-5 граблей, на которые наступают команды при внедрении
⏱️ 10 марта в 19:00 (МСК)
🎁 Участники получат промокод на скидку на самый полный курс по ИИ-агентам
👉 Регистрируйся
🔎 Microsoft Foundry: февраль 2026
В феврале Foundry получил существенный апдейт. Вышли Claude 4.6 от Anthropic и Grok 4.0 от xAI, Agent Framework достиг release candidate с серьезными изменениями, и все SDK переходят на единую REST архитектуру.
Новые модели
Claude Opus 4.6 и Claude Sonnet 4.6 теперь доступны в Foundry. Opus для сложного рассуждения, Sonnet примерно того же уровня, но дешевле. Оба поддерживают миллион токенов контекста и 128K токенов в ответе.
Grok 4.0 от xAI стал GA. Одновременно вышла Grok 4.1 Fast для классификации и маршрутизации без рассуждений: 0.20 долларов за миллион на вход.
GPT-Realtime-1.5 и GPT-Audio-1.5 улучшили следование инструкциям на 7% и точность транскрипции на 10%.
FLUX.2 Flex специально для UI дизайна с текстом.
Agent Framework: Release Candidate и HITL
Agent Framework вышел в 1.0.0rc1 с замороженным API. Общий выпуск уже рядом, но есть разрывающие изменения.
Главные перемены:
• Учетные данные теперь используют Azure Identity вместо токена
• Сессии вместо потока
• response.messages вместо response.text
• create_version() вместо create()
• Предварительные операции в подкаталоге .beta
REST API v1 GA
Foundry REST API v1 теперь production-ready. Все основные эндпоинты заморожены: чаты, ответы, встраивания, файлы, тонкая настройка, модели, хранилища векторов.
Если ваш SDK еще в pre-release, можете запросить REST API напрямую.
SDK обновления
.NET 2.0.0-beta.1: ImageBasedHostedAgentDefinition объединили с HostedAgentDefinition.
Foundry Local и VS Code
Foundry Local теперь поддерживает большие мультимодальные модели полностью автономно без облака.
AI Toolkit for VS Code v0.30.0 добавил Tool Catalog для поиска инструментов, Agent Inspector для дебага с F5 breakpoints и переделанный Agent Builder.
В марте SDK будут общедоступны. Обновитесь к RC сейчас, если используете.
➡️ Блог разработчиков
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#async_news
🤔 Вопрос с собеса
Классика интервью:
Что такое readonly struct и чем он отличается от обычной структуры
📝 Вытащить текст из PDF на C#
Иногда нужно просто достать текст из PDF — для скрипта, личного инструмента или быстрой автоматизации под себя. Руками копировать лень, особенно если файлов несколько. Вот способ сделать это на C# без лишних телодвижений.
Что использовать
Библиотека Free Spire.PDF для .NET. Устанавливается через NuGet одной командой и не требует ничего стороннего — ни ридеров, ни внешних утилит.
Install-Package FreeSpire.PDF
PdfDocument doc = new PdfDocument();
doc.LoadFromFile("Sample.pdf");
PdfPageBase page = doc.Pages[1]; // вторая страница
PdfTextExtractor extractor = new PdfTextExtractor(page);
PdfTextExtractOptions options = new PdfTextExtractOptions { IsExtractAllText = true };
string text = extractor.ExtractText(options);
File.WriteAllText("output.txt", text);
doc.Close();
StringBuilder allText = new StringBuilder();
foreach (PdfPageBase page in doc.Pages)
{
var extractor = new PdfTextExtractor(page);
var options = new PdfTextExtractOptions { IsExtractAllText = true };
allText.AppendLine(extractor.ExtractText(options));
}
File.WriteAllText("output.txt", allText.ToString());
LoadFromFile. Если нужен текст только из конкретной области страницы — задаёшь прямоугольник через ExtractArea в точках (1 point = 1/72 дюйма). PdfTableExtractor, который возвращает данные в виде массива. Сканы и нечитаемые PDF решаются через Spire.OCR в связке с основной библиотекой.
👨💻 NuGet стал удобнее
Разработчик запустил nugetz.dev — альтернативный интерфейс для поиска по реестру NuGet.
Стандартный поиск на nuget.org работает, но медленно и неудобно. Когда выбираешь библиотеку, хочешь быстро понять: пакет живой, как давно обновлялся, насколько популярен. Сейчас это занимает лишнее время.
Nugetz решает именно это. Тот же реестр, но с чистым интерфейсом, быстрой выдачей и без лишнего шума на экране. Без регистрации и рекламы.
Идея пришла от npmx — похожего инструмента для npm-экосистемы. Rodrigo просто спросил себя, почему у .NET такого нет, и сделал.
➡️ Попробовать
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#пульс_индустрии
😎 Подборка вакансий для шарпистов
C# backend-разработчик в команду Security — Офис/гибрид в Москве
Backend Engineer — от 175 000 до 325 000 ₽, удалёнка
C#/.NET разработчик — от 350 000 ₽, удалёнка
Бустер — Удалённо в любом городе мира.
➡️ Еще больше топовых вакансий — в нашем канале C# Jobs
🐸 Библиотека шарписта
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#garbage_collector
🔌 Пишите интерфейс так, чтобы не объяснять
Хороший код легко использовать правильно — и сложно использовать неправильно. Это важно при проектировании API: даже внутреннего.
На ревью кода интерфейсов проверяют логику, покрытие тестами, производительность. Но неудобный интерфейс это технический долг, который будет копиться каждый раз, когда кто-то будет использовать этот код.
Вот на что стоит обращать внимание:
• Понятен ли смысл метода. Название должно говорить само за себя без комментария над функцией и без погружения в реализацию.
Если приходится читать тело метода, чтобы понять что он делает, значит имя плохое.
• Предсказуемо ли поведение. Метод с одинаковыми параметрами должен возвращать одинаковый результат.
Скрытые побочные эффекты и неочевидные состояния — прямой путь к багам, которые воспроизводятся через раз.
• Булевые флаги это тревожный знак. Два булевых параметра подряд — почти всегда признак того, что функция делает слишком много или интерфейс не доработан:
ProcessData(bool flag1, bool flag2);
ProcessData(ProcessMode mode, ValidationOptions options);
👨💻 Генерируйте 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' ...
🔄 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"));#tool и InstallTool можно устанавливать любые NuGet пакеты прямо в инструменты..slnx файлов. DotNetTest и парсинг решений теперь распознают XML-формат solution файлов, а автоопределение типа пути включает .slnx.
Энтерпрайз убивает драйв? Стань техническим кофаундером в 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
🌍 Сравнение строк и культура
Когда вы сравниваете строки в 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 на турецкой машине!
👨💻 string в C# — не просто текст
string — это ссылочный тип с особой поддержкой рантайма. Внутри он хранит непрерывный блок UTF-16 кодовых единиц.
Отсюда первый сюрприз:
string s = "😊";
Console.WriteLine(s.Length); // 2, не 1
❓ Что выведет код
Сделали сниппет кода на манер JavaScript, складываем число и строку. В C#, в отличие от JS, это операция предсказуемая и можно догадаться о результате.
➡️ Проверьте себя не запуская код
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#dotnet_challenge
🔍 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