23284
Все самое полезное для C#-разработчика в одном канале. По рекламе: @proglib_adv Учиться у нас: https://proglib.io/w/b60af5a4 Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead
✏️ Задача без подвоха
Дан массив длиной 2n в виде [x1,x2,xn,y1,y2,yn] нужно вернуть массив [x1,y1,x2,y2,xn,yn], то есть перемешать.
Идея решения
Логически делим массив на две половины по n элементов и в одном цикле по индексу i собираем ответ в новый массив result.
На каждой итерации кладем сначала элемент из первой половины nums[i] потом из второй nums[i+n].
Так мы проходим вход один раз время O(n), где n это половина массива.
Решение:
public class Solution
{
public int[] Shuffle(int[] nums, int n)
{
int[] result = new int[2 * n];
int index = 0;
for (int i = 0; i < n; i++)
{
result[index++] = nums[i];
result[index] = nums[i + n];
index++;
}
return result;
}
}
n минус один вторая от n до 2n минус один, а индекс в result просто сдвигается на два шага за итерацию.
🧑💻 Честность в айти — это грех
В айти часто говорят, что честность — это слабость. Многие накручивают опыт, преувеличивают достижения и скрывают ошибки, чтобы выглядеть лучше в резюме.
Но без честности не бывает доверия и настоящего развития. Признание своих ошибок и реальных навыков помогает учиться и двигаться вперед, а не строить пирамиду из лжи.
💬 Как думаете лучше приврать или сказать как есть? Где ложь во благо, а где во вред? Делитесь в комментах своими размышлениями 👇
🔹 Практический интенсив «Архитектуры и шаблоны проектирования»
🔹 Получить консультацию менеджера
🔹 Сайт Академии 🔹 Сайт Proglib
🐸Библиотека шарписта
#entry_point
🔑 Управление HttpClient по ключам
С .NET 9 можно управлять зависимостями по ключам. Буквально регистрировать и получать, к примеру, конфиги для HttpClient.
Как это работает
• AddAsKeyed() — новый метод расширения для регистрации именованных HttpClient как Keyed Service в DI. Имя клиента становится ключом, по которому можно получать конкретный экземпляр.
• Внедрение осуществляется с помощью атрибута [FromKeyedServices("key")] или через Func<string, HttpClient> для динамического выбора клиента по ключу.
• В отличие от старых подходов с именованными или типизированными клиентами, внедрение зависимостей по ключам позволяет упростить код и уменьшить лишние вызовы фабрики IHttpClientFactory.
Пример регистрации и использования:
var builder = WebApplication.CreateBuilder(args);
// Регистрация HttpClient с ключом "github"
builder.Services.AddHttpClient("github", c =>
{
c.BaseAddress = new Uri("https://api.github.com/");
c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
c.DefaultRequestHeaders.Add("User-Agent", "dotnet");
})
.AddAsKeyed();
var app = builder.Build();
// Внедрение HttpClient по ключу "github"
app.MapGet("/", ([FromKeyedServices("github")] HttpClient httpClient) =>
{
return httpClient.GetFromJsonAsync<Repo>("/repos/dotnet/runtime");
});
app.Run();
record Repo(string Name, string Url);
IHttpClientFactory.ConfigureHttpClientDefaults.AddAsKeyed() регистрирует HttpClient с областью видимости Scoped, но можно настроить и другой жизненный цикл.
👨💻 Поддержка and! в task-вычислениях F# 10
В F# 10 библиотека FSharp.Core получила улучшение — поддержку оператора and! в вычислительном выражении task.
Раньше, чтобы ждать несколько задач параллельно, нужно было либо ждать их последовательно:
task {
let! a = fetchA()
let! b = fetchB()
return combineAB a b
}Task.WhenAll для ожидания сразу всех:task {
let ta = fetchA()
let tb = fetchB()
let! results = Task.WhenAll([| ta; tb |])
return combineAB ta.Result tb.Result
}task {
let! a = fetchA()
and! b = fetchB()
return combineAB a b
}
Math for .NET Developers
Использовать ML.NET или Accord.net — это полдела. Чтобы кастомизировать модели и понимать, почему сеть не сходится, нужно лезть под капот. Там живут матрицы, производные и векторы.
Завтра стартуем курс «Математика для разработки AI-моделей».
🛠 Темы: Линал, матан, теорвер.
💸 Цена: 28 200 ₽ (новогодний прайс).
⏱ Дедлайн: Старт завтра.
Интегрируйте знания в свой стек:
🔗 Ссылка на курс
Debug your math: @proglib_academy_webinar_bot
🛠 Строгая проверка назначения атрибутов в F# 10
В F# 10 компилятор стал жёстко проверять, что атрибуты применяются только к тем конструкциям, для которых они предназначены. Это касается функций, значений, объединений, конструкторов, структур, классов и других элементов.
Раньше F# позволял неявно применять атрибуты к неподходящим целям без предупреждений. Из-за этого возникали баги, например:
• Тестовые атрибуты не работали, если функция не имела (), и тесты не запускались
• Атрибуты-анализаторы иногда игнорировались, приводя к сбоям в CI без очевидной причины.
Пример такого кода, который никак не работал:
[<Fact>]
let ``this is not a function`` = // никак не запускался тест
Assert.True(false)
[<Fact>]
//^^^^ предупреждение FS0842: атрибут нельзя применять к свойству, полю и т.п.
let ``works correctly`` =
Assert.True(true)
🌲 Подборка вакансий для шарпистов
C#/.NET Developer на удалёнку
C#/.NET Developer с ЗП от 2 500 до 5 000$
C# / .NET Разработчик, middle, middle+ — от 190 000 до 290 000 ₽
🔸 AI-агенты для DS-специалистов
🔸 Получить консультацию менеджера
🔸 Сайт Академии 🔸 Сайт Proglib
➡️ Еще больше топовых вакансий — в нашем канале C# Jobs
🐸 Библиотека шарписта
🐸Библиотека шарписта
#garbage_collector
📘 4 декабря стартует набор на курс «Математика для разработки AI-моделей»
Если вы работаете с моделями или хотите перейти в DS/ML, декабрь — идеальный момент закрыть фундаментальные пробелы.
На курсе вы разберёте ключевые разделы, которые лежат в основе современных AI-моделей: линейная алгебра, анализ, оптимизация, математический анализ, вероятности, статистика. Всё через практику в Python.
В программе живые занятия с экспертами AI-индустрии (SberAI, ВШЭ, WB&Russ), разбор реальных задач, квизы и финальный проект.
🌐 Формат: онлайн + доступ к записям
🎁 Бонусы: курс «Школьная математика» в подарок, бесплатный тест по математике
После лекций будет разбор ваших решений и возможность задать вопросы преподавателям.
👉 Записаться на курс
✋ Хватит плохих новостей
Такое ощущение, что плохих новостей вокруг уже больше, чем уведомлений от коллег.
Наткнулись на канал с позитивными новостями и это как антидот к новостному шуму и думскроллингу, где можно сознательно переключиться в режим «у мира ещё есть шансы».
🤌 Бонусы для подписчиков:
— Скидка 40% на все курсы Академии
— Розыгрыш Apple MacBook
— Бесплатный тест на знание математики
🐸Библиотека шарписта
🔥 Хочешь строить свои AI-модели, а не просто запускать чужие?
Proglib.academy открывает курс «Математика для разработки AI-моделей» — программу, которая превращает понимание ML из «черного ящика» в осознанную инженерную работу.
📌 Почему без математики в AI никуда:
→ Чтобы пройти собеседование. Это первый фильтр: линал, матстат, оптимизация — спрашивают везде.
→ Чтобы понимать процесс изнутри. Инженер AI должен понимать, почему и как работает модель, а не просто жать fit().
🎓 Что будет на курсе:
→ 3 практических задания на Python + финальный проект с разбором от специалистов;
→ программа обновлена в ноябре 2025;
→ за 2 месяца пройдёшь весь фундамент, нужный для работы с моделями;
→ преподаватели — гуру математики, методисты и исследователи из ВШЭ и индустрии.
🎁 Бонусы ноября:
— 40% скидка;
— получаешь курс «Школьная математика» в подарок;
— короткий тест и узнать свой уровень.
🔗 Подробнее о курсе
😂 Я ставлю X. Ваш ход
🐸Библиотека шарписта
#garbage_collector
💳 Как выбить зарплату побольше
Собрали для вас в карточках 5 стратегий для торгов на собеседовании. Есть ещё несколько, которые подробно описаны в статье.
🤌 Бонусы для подписчиков:
— Скидка 40% на все курсы Академии
— Розыгрыш Apple MacBook
— Бесплатный тест на знание математики
🐸Библиотека шарписта
💡 Tail-call оптимизация в вычислительных выражениях F# 10
В F# 10 появилась важная возможность оптимизировать использование вычислительных выражений с помощью поддержки tail-call оптимизации для ключевых вызовов return!, yield! и do!.
Теперь компилятор распознаёт, когда эти вызовы находятся в хвостовой позиции, и, если реализация билдера поддерживает специальные методы ReturnFromFinal, YieldFromFinal и им подобные, он применяет оптимизацию tail call. Это позволяет выполнять вызовы без дополнительного роста стека.
🔹 Основы IT для непрограммистов
🔹 Получить консультацию менеджера
🔹 Сайт Академии 🔹 Сайт Proglib
🐸 Библиотека шарписта
#sharp_view
👨💻 Обработка ошибок в .NET minimal API
При разработке API важно правильно и понятно передавать клиентам информацию о возникших ошибках.
Одним из удобных способов сделать это в .NET minimal API является использование встроенного метода Results.Problem. Он возвращает объект с подробностями ошибки в стандарте ProblemDetails, что упрощает клиентам обработку ответа.
Пример:
app.MapGet("/users/{id}", async (string id, IUserRepo repo) =>
{
if (!Guid.TryParse(id, out var guid))
return Results.Problem("Invalid id", statusCode: 400);
var user = await repo.Find(guid);
return user is null ? Results.NotFound() : Results.Ok(user);
});
C# мощный, но математика универсальна
ML.NET развивается, но фундамент Data Science остаётся неизменным. Чтобы эффективно работать с данными (даже в .NET-среде), нужно понимать линейную алгебру и статистику.
Мы добавили живые вебинары в наш курс по математике для AI.
Программа ближайших лекций:
— Vectors & Matrices: операции, ранги, СЛАУ;
— Linear Regression: реализация МНК, интерпретация весов;
— SVD: матричные разложения и рекомендательные системы.
Практика на Python (NumPy), но алгоритмическая суть переносится на любой язык.
Регистрация закрывается 9 декабря:
https://clc.to/LojFzw
🔄 Отмена запросов в EF
В реальных приложениях бывают ситуации, когда нужно прервать долгую операцию с базой данных, если она больше не актуальна или пользователь отменил действие.
Долгие запросы или операции сохранения могут повиснуть или перерасходовать системные ресурсы, если не предусмотрена возможность прерывания.
В Entity Framework для управления отменой используется CancellationToken. Его можно передавать в асинхронные методы, например:
await db.SaveChangesAsync(ct);
❗️ Microsoft признала масштабный баг в интерфейсе Windows 11 24H2 и 25H2
У части пользователей Windows 11 после установки последних обновлений в версиях 24H2 и 25H2 начали ломаться ключевые элементы интерфейса.
Проблема затрагивает базовые функции оболочки и выглядит как обычный «заглючивший» рабочий стол, но на деле связана с ошибками в самих системных компонентах.
Временное решение — установка актуальных патчей, использование опубликованных обходных скриптов или откат проблемных обновлений, если интерфейс стал нестабильным после апдейта.
➡️ Источник
🔹 Математика для разработки AI-моделей
🔹 Получить консультацию менеджера
🔹 Сайт Академии 🔹 Сайт Proglib
🐸Библиотека шарписта
#async_news
⚙️ Используйте AsNoTracking() для запросов только на чтение
Если нужно получить данные из базы без их изменения, лучше использовать AsNoTracking():
var posts = await db.Posts.AsNoTracking()
.Where(p => p.Published)
.ToListAsync(ct);
AsNoTracking() говорит Entity Framework не отслеживать изменения для полученных объектов.
🛠 .NET MAUI и работа с возрастом
С началом 2026 года в США вступают в силу новые требования по верификации возраста пользователей для мобильных и десктопных приложений.
Да, это затрагивает несколько штатов в США, но стоит держать руку на пульсе.
.NET MAUI предоставляет удобный способ решения этой задачи с помощью единого интерфейса IAgeSignalService и трёх платформо-специфичных реализаций:
• Для Android используется Google Play Age Signals API, который возвращает пять статусов в зависимости от ситуации: от подтверждённого возраста до ожидания одобрения опекуна.
• На iOS применяется Apple Declared Age Range API, работающий на устройствах с iOS 26 и выше, отображающий возрастной диапазон и информацию о том, кто его подтвердил — сам пользователь или опекун.
• Windows предлагает Windows Age Consent API с упрощённой классификацией пользователей на три категории: ребёнок, несовершеннолетний и взрослый.
Главное преимущество — единая точка интеграции и адаптация под каждый API за счёт условной компиляции и инъекции зависимостей. Достаточно подключить сервис в MauiProgram, чтобы обеспечить проверку возраста на нужной платформе.
➡️ Блог Microsoft
🔹 AI-агенты для DS-специалистов
🔹 Получить консультацию менеджера
🔹 Сайт Академии 🔹 Сайт Proglib
🐸Библиотека шарписта
#sharp_view
🧑💻 Проекция колонок вместо сущностей в запросах
Когда работаете с базой данных, лучше получить только нужные поля, а не всю сущность. Это ускорит запросы и снизит объём передаваемых данных.
Пример проекции колонок с использованием LINQ:
var dto = await db.Users
.Where(u => u.Id == id)
.Select(u => new UserDto(u.Id, u.Name))
.SingleOrDefaultAsync(ct);
🔍 Устаревший синтаксис в F# 10
Раньше F# позволял опускать ключевое слово seq при создании последовательностей, что выглядело так:
{ 1..10 } |> List.ofSeq // неявная последовательностьseq { 1..10 } |> List.ofSeq
📞 Комбинации букв телефонного номера: решение за один проход рекурсии
Задача — сгенерировать все возможные буквенные комбинации по цифрам телефона, где каждая цифра соответствует набору букв.
Идея решения: для каждой цифры берём соответствующие буквы и рекурсивно добавляем их к уже сформированным комбинациям.
Алгоритм:
1. Если входная строка пуста, возвращаем пустой результат
2. Используем массив с отображением цифр на наборы букв.
3. Рекурсивно проходим по цифрам, добавляя буквы к текущей комбинации
4. Когда достигнут конец строки, сохраняем сформированную комбинацию.
Решение:
public class Solution {
private static readonly string[] map = { "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" };
public IList<string> LetterCombinations(string digits) {
var result = new List<string>();
if(string.IsNullOrEmpty(digits))
return result;
Backtrack(digits, 0, new StringBuilder(), result);
return result;
}
private void Backtrack(string digits, int index, StringBuilder current, List<string> result) {
if(index == digits.Length) {
result.Add(current.ToString());
return;
}
string letters = map[digits[index] - '0'];
foreach(char c in letters) {
current.Append(c);
Backtrack(digits, index + 1, current, result);
current.Length--;
}
}
}
✏️ Запрет псевдо-вложенных модулей внутри типов в F# 10
В F# 10 добавили важное правило: теперь нельзя объявлять модуль внутри определения типа с тем же уровнем отступа, как сам тип.
Это выглядело как вложенный модуль, но на самом деле модуль создавался на одном уровне с типом — то есть был соседом, а не дочерним элементом.
Пример из старого кода:
type U =
| A
| B
module M = // на самом деле не вложенный модуль
let f () = ()
type U =
| A
| B
module M =
let f () = ()
📰 Последняя неделя ноября
Ноябрь вот-вот закончится, а мы подводим итоги недели.
— Куда катится .NET
Microsoft выкатили большой лонгрид про то, как .NET в .NET 10 окончательно переезжает на Unified Build — виртуальный монорепозиторий и вертикальные сборки, чтобы быстрее и предсказуемее собирать весь продукт.
— Ивент про ИИ
.NET‑команда анонсировала бесплатный онлайн‑ивент .NET Day on Agentic Modernization, который пройдёт 9 декабря 2025
— Redis 8.4
Redis выкатили версию, которая одновременно ускоряет кэш, упрощает жизнь кластерам и делает Redis куда более удобным движком для AI и гибридного поиска
— GitHub Copilot Testing
— Перестаньте ждать, пока вас найдут
— Карьерная «страховка» для IT‑шника
🫶 Бонусы для подписчиков:
— Скидка 40% на все курсы Академии
— Розыгрыш Apple MacBook
— Бесплатный тест на знание математики
🐸Библиотека шарписта
#async_news
👨💻 DbContext в ASP.NET Core лучше оставлять scoped
В ASP.NET Core есть негласное правило DbContext живет ровно столько, сколько живет HTTP запрос. Эту модель Microsoft прямо закладывает в документацию, ведь DbContext задуман как короткоживущий объект под одну единицу работы одну бизнес операцию и один вызов SaveChanges.
Когда вы регистрируете контекст так:
builder.Services.AddDbContext<AppDb>(opt =>
opt.UseNpgsql(connString));
💻 Поддержка паттерна discard в use! в F# 10
Раньше в use! вычислительных выражениях нельзя было указать _ для игнорирования результата, что заставляло создавать ненужные имена переменных, например, __ или _ignored.
Теперь можно прямо написать:
use! _ = acquireResourceAsync()
⚡️ Batch-обработка с помощью Chunk
Если нужно обработать коллекцию по частям — например, выгрузить данные пакетами, есть решение: метод Chunk. Он создаёт из исходного списка последовательность подсписков одинакового размера.
Пример:
foreach (var batch in items.Chunk(100))
{
await SaveBatch(batch);
}
💼 Карьерная «страховка» для IT‑шника
Рынок IT сильно изменился за последние годы. После бурного роста начались крупные сокращения и оптимизация команд. Сегодня никто не может быть уверен в стабильности работы — даже опытные разработчики сталкиваются с риском внезапного увольнения.
Поэтому важно задуматься о своей карьерной страховке — простых шагах и инструментах, которые помогут защитить себя и сохранить финансовую устойчивость в любой ситуации.
➡️ Собрать свою страховку
🔸 ML для старта в Data Science
🔸 Получить консультацию менеджера
🔸 Сайт Академии 🔸 Сайт Proglib
🐸Библиотека шарписта
🤩 Типизированные вычислительные выражения в F# 10 без скобок
В F# 10 упростили синтаксис для аннотирования типов в вычислительных выражениях. Теперь можно добавлять типы в let!, use! и and! без необходимости использовать дополнительные скобки вокруг идентификаторов.
ньше для указания типа в вычислительном выражении приходилось писать так:
let! (x: int) = fetchValue()
let! x: int = fetchValue()