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

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

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

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

РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead
Download Telegram
🌐 Браузер без всего лишнего

Наткнулись на проект, который помогает вырезать из Chrome, Edge и Firefox всё лишнее, что не относится к работе браузера.

Что сносит:

• AI-фичи (Copilot в Edge, AI-саммари в Chrome)
• Телеметрия и отчёты об использовании
• Спонсорский контент и реклама
• Интеграция сторонних продуктов
• Рекомендованные новости и виджеты
• Бесполезные UI-элементы

Вместо ручного копания в about:config или реестре Windows — готовые конфиги + скрипты установки.

➡️ Удалить мусор из браузера

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

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

#async_news
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥7👍2😢2😁1
⚡️ Чистый LINQ, грязные аллокации

Проблема LINQ в горячих местах обычно не в вычислениях, а в том, что вокруг каждого запроса появляются маленькие кусочки инфраструктуры.

Where и Select сами по себе ленивые, они не выполняются пока не началось перечисление. Но как только появляется ToArray, начинается реальная работа и выделяется новый массив под результат

Если внутри цикла постоянно вызывается ToArray, то постоянно создаются новые массивы.
Если еще и лямбды захватывают переменные, добавляются лишние замыкания, и это тоже может стать частью мусора, который потом будет собирать GC.

Пример:
foreach (var batch in batches)
{
var validItems = batch
.Where(IsValid)
.Select(Transform)
.ToArray();

Process(validItems);
}


Ручной цикл выглядит скучнее, но дает контроль над буфером и позволяет переиспользовать память:
var buffer = new List<Result>(batch.Count);

foreach (var item in batch)
{
if (!IsValid(item))
continue;
buffer.Add(Transform(item));
}
Process(CollectionsMarshal.AsSpan(buffer));
buffer.Clear();


CollectionsMarshal.AsSpan дает доступ к внутреннему массиву List как Span, то есть можно передать данные дальше без копирования, но важно не менять List пока Span используется.

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

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱7👍5👾51
🏭 Новая база корпоративной культуры

В 2025 году индустрия провела эксперимент и пришла к циничному выводу: забота о сотрудниках экономически невыгодна. Теперь карьерный рост зависит не от крутого продукта, а от способности закрывать KPI и не сгореть раньше коллег.

Почему так произошло и кто в этом виноват — разбираемся в статье.

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

🐸Библиотека шарписта
Please open Telegram to view this post
VIEW IN TELEGRAM
😢3👏1🤩1🥱1
🤩 Громкость прокруткой колеса

В дефолтном микшере Windows 11 для настройки громкости отдельных приложений нужно сделать много действий:

1. В меню найти иконку громкости и кликнуть по ней
2. Кликнуть по ещё одной иконке в выпавшем меню
3. Пролистать вниз и настроить громкость.

Мод с Windhawk меняет это: наводим на иконку звука в таскбаре — прокручиваем колёсико мыши — сразу меняем громкость активного приложения.

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

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

#async_news
Please open Telegram to view this post
VIEW IN TELEGRAM
4
📎 SelectMany это двойной foreach, просто в красивой упаковке

SelectMany проектирует каждый элемент во вложенную последовательность и потом склеивает эти последовательности в одну общую.

И это отличный выбор для чистой проекции без сложной логики, когда нужно ровно развернуть коллекцию коллекций.

Но если в задаче появляется управление потоком или условия выхода:
var allItems = orders
.SelectMany(o => o.Items)
.Where(i => i.IsActive)
.ToList();


Цикл часто дает больше ясности и предсказуемости:
var allItems = new List<Item>();

foreach (var order in orders)
{
foreach (var item in order.Items)
{
if (!item.IsActive)
continue;
allItems.Add(item);
}
}


Плюс тут легко вставить break, continue, счетчики, ограничения, и не гадать как они сложатся с отложенным выполнением.

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

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔9😁1🥱1
«Этот манёвр будет стоить нам 51 год...»

Для .NET разработчика архитектура и алгоритмы — это база. Если вы хотите проектировать сложные системы или внедрять ИИ в свои энтерпрайз-решения, сейчас лучший момент для старта.

В Proglib Academy поднимаются цены. Успейте забрать курс по старой стоимости:

— Разработка ИИ-агентов
— Математика для разработки AI-моделей
— ML для старта в Data Science
— Математика для Data Science
— Специалист по ИИ
— Алгоритмы и структуры данных
— Программирование на Python
— Основы IT для непрограммистов
— Архитектуры и шаблоны проектирования

Забрать по старой цене

⚠️ Повышение уже 19 января
🥱4
👨‍💻 Когда if начинает распухать

Паттерн стратегия подходит, когда один и тот же сценарий можно выполнить несколькими способами, и выбор зависит от условий. Вместо большого switch внутри сервиса разные варианты выносятся в отдельные классы с общим интерфейсом, а контекст просто делегирует работу выбранной реализации.

Типовая схема такая. Есть интерфейс Strategy, есть несколько конкретных стратегий, и есть контекст, который держит ссылку на стратегию и вызывает ее метод, не зная деталей реализации. Это снижает связность и позволяет добавлять новые варианты без переписывания старого кода.

Мини пример на C#:
public interface IDiscountStrategy
{
decimal Apply(decimal total);
}

public sealed class RegularDiscount : IDiscountStrategy
{
public decimal Apply(decimal total) => total;
}

public sealed class VipDiscount : IDiscountStrategy
{
public decimal Apply(decimal total) => total * 0.9m;
}

public sealed class Checkout
{
private readonly IDiscountStrategy _discount;

public Checkout(IDiscountStrategy discount) => _discount = discount;

public decimal TotalWithDiscount(decimal total) => _discount.Apply(total);
}


Если стратегия выбирается по условиям, условие должно выбирать объект, а не ветку кода:
var checkout = serviceProvider.GetRequiredService<Checkout>();
var total = checkout.TotalWithDiscount(100m);


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

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

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
12
🔄 .NET: январские обновления

Microsoft выпустила очередную порцию сервисных обновлений для платформы .NET. Вышли новые версии для трёх поддерживаемых веток:

.NET 10.0.2 — самая свежая версия платформы
.NET 9.0.12 — актуальная STS-версия
.NET 8.0.23 — предыдущая LTS-версия

➡️ Блог разработчиков

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

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

#async_news
Please open Telegram to view this post
VIEW IN TELEGRAM
🌚2
🧑‍💻 Исключения — не для обычного управления потоком

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

Антипаттерн, который всё ещё встречается:
{
var value = dictionary[key];
Process(value);
}
catch (KeyNotFoundException)
{
// ignore
}


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

Правильный подход — явное ветвление:
if (dictionary.TryGetValue(key, out var value))
{
Process(value);
}


Этот код читается понятно, работает быстрее и сохраняет исключения значимыми.

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

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱96👍5😁2
👼 Дайджест первой недели

Прошла первая рабочая неделя 2026 года. Собираем яркие материалы и новости в один пост.

Microsoft показали как делать виджеты

Удаляем хлам из браузера

Новая база корпоративной культуры

Январские обновления .NET

Скоро будет домен .meow

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

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

#async_news
Please open Telegram to view this post
VIEW IN TELEGRAM
2
public const Price = OldPrice; // до 20.01

Мы меняем значение константы: завтра обучение станет дороже. Успейте пробросить заказ сегодня, чтобы зафиксировать текущую стоимость в своём стеке.

Инициализировать рост компетенций
🥱2👍1
🚀 Одна строка кода для ускорения EF Core

Когда EF Core загружает связанные сущности через Include(), он генерирует один огромный SQL-запрос с множеством JOIN. Результат? Тысячи дублирующихся строк, гигабайты трафика и медленная работа.

Пример:
var posts = await context.Posts
.Include(p => p.Comments)
.ThenInclude(c => c.Reactions)
.ToListAsync();


При 100 постах, у каждого по 10 комментариев, в каждом по 10 реакций — вместо 11 100 записей получаем результирующий набор на 10 000 строк.

Добавьте .AsSplitQuery() — и EF Core разобьёт один большой запрос на несколько маленьких:
var posts = await context.Posts
.AsSplitQuery() // ← магия здесь
.Include(p => p.Comments)
.ThenInclude(c => c.Reactions)
.ToListAsync();


Query Splitting — это не хак и не костыль. Это правильный способ работы с EF Core в read-heavy сценариях.

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

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

#il_люминатор
Please open Telegram to view this post
VIEW IN TELEGRAM
👍211😁1
🛠 Parallel.For — когда циклы работают параллельно

Представьте: у вас есть массив из миллиона элементов, и каждый нужно обработать. Обычный цикл for будет делать это последовательно — один элемент за другим. А что если задействовать все ядра процессора?

Базовое использование:
// Было
for (int i = 0; i < 1000; i++)
{
ProcessImage(images[i]);
}

// Стало
Parallel.For(0, 1000, i =>
{
ProcessImage(images[i]);
});


Вот и всё. Task Parallel Library сам распределит работу по потокам, сам управляет ThreadPool, сам балансирует нагрузку.

Когда это имеет смысл:

+ Обработка изображений, видео
+ Математические вычисления
+ Парсинг больших объёмов данных
+ Криптографические операции


Не подходит:

- Обработка меньше 100 элементов
- Операции с базой данных или API
- Быстрые операции вроде i * 2

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

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
15🥱2
👍 JIT .NET 10 убирает абстракции почти бесплатно

В .NET 10 Microsoft сильно доработали JIT компилятор. Цель простая сделать так, чтобы привычный высокоуровневый С# код работал почти как вручную вылизанный низкоуровневый.

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

Ключевой механизм это улучшенный escape analysis. Если JIT может доказать, что объект живет только внутри метода не передается наружу и не сохраняется в поля, он размещает его на стеке.

Пример:
[Benchmark]
[Arguments(42)]
public int SumWithOffset(int offset)
{
Func<int, int> addOffset = value => value + offset;
return ApplyTwice(addOffset, offset);
}


В старой версии платформы такой код почти гарантировал лишнюю аллокацию делегата и замыкания в куче.

По сути JIT делает за разработчика ту оптимизацию которую раньше приходилось реализовывать вручную через отказ от лямбд и делегатов на горячем пути.

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

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

#il_люминатор
Please open Telegram to view this post
VIEW IN TELEGRAM
👍29
📎 Преобразование Excel в JSON

Сделаем минимальный код для чтения таблиц для конвертации в JSON.

Подключите NuGet-пакеты FreeSpire.XLS и Newtonsoft.Json. Первая читает .xlsx без зависимостей, вторая формирует JSON.

Код начинается с загрузки файла в поток. Библиотека преобразует лист в DataSet, где строки становятся объектами. Первая строка служит заголовками полей.

Чтение и конвертация данных:
using Spire.Xls;
using Newtonsoft.Json;

Workbook wb = new Workbook();
wb.LoadFromFile("данные.xlsx");
DataTable таблица = wb.Worksheets.ExportDataTable();

JsonSerializerSettings опции = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
NullValueHandling = NullValueHandling.Ignore
};

string результат = JsonConvert.SerializeObject(таблица, опции);
File.WriteAllText("выход.json", результат);


Игнорируйте null для компактности. Форматируйте даты единообразно. Тестируйте на реальных данных — библиотека FreeSpire.XLS ограничена объемом, но достаточна для большинства случаев.

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

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🥱2
🧬 Мутационное тестирование

Вы пишете unit-тесты, coverage показывает 80-90%, но уверены ли вы, что эти тесты реально ловят баги? Мутационное тестирование помогает проверить качество самих тестов.

Суть подхода

Инструмент автоматически вносит небольшие изменения в ваш код: меняет операторы, условия, константы. Если тесты проходят с «поломанным» кодом — значит, они недостаточно строгие.

Stryker.NET в действии

Установка занимает пару минут через dotnet tool. После запуска Stryker анализирует код, создаёт мутантов и прогоняет по ним тесты. В отчёте вы видите:

• Какие мутации выжили
• Mutation Score — процент убитых мутантов
• Конкретные строки кода, где тесты слабые

Практический пример

Допустим, у вас метод проверяет возраст пользователя. Stryker меняет age >= 18 на age > 18. Если тест с граничным значением 18 отсутствует — мутант выживает, и вы понимаете, где дописать проверку.

Stryker умеет работать с xUnit, NUnit, MSTest. Настраивается через JSON-файл, где можно указать пороговые значения mutation score, исключить файлы из анализа, настроить уровни логирования.

Процесс требует времени — каждая мутация прогоняет весь набор тестов. Но результат того стоит: вы находите слепые зоны в тестовом покрытии, которые обычный coverage не показывает.

➡️ Репозиторий

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

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

#il_люминатор
Please open Telegram to view this post
VIEW IN TELEGRAM
14🤔3
🔄 NBomber 6.2.0: фильтрация метрик, OpenTelemetry и улучшенные отчёты

NBomber — это фреймворк для распределённого нагрузочного тестирования в .NET. Вы пишете сценарии на обычном C# или F#, тестируете любые системы независимо от протокола и модели взаимодействия.

Что нового в версии 6.2.0:

Теперь можно фильтровать метрики по имени — полезно, когда у вас десятки показателей. На графике Throughput отображается Fail RPS, так что проблемы видны сразу.

Кластерный режим теперь настраивается через CLI без JSON-конфига. Можно указать целевые сценарии, а группы агентов стали опциональными.

Реализована интеграция с OpenTelemetry — теперь метрики можно отправлять в стандартные системы мониторинга.

➡️ Релиз на GitHub

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

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

#async_news
Please open Telegram to view this post
VIEW IN TELEGRAM
👍43
This media is not supported in your browser
VIEW IN TELEGRAM
😁31