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

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

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

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

РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead
Download Telegram
💥 Октябрь — месяц апгрейда!

До конца этого месяца действует скидка 40% на все курсы Proglib Academy (кроме AI-агентов, ML для старта и математики).

Под акцию попал и наш хит — курс «Алгоритмы и структуры данных».

👨‍💻 Он подойдёт джунам, мидлам и всем, кто хочет писать код осознанно, а не наугад.

👨‍🏫 Преподаватели — инженеры из Яндекса и ВШЭ.

🎓 Сертификат по итогам обучения — в портфолио.

47 видеоуроков и 150 практических задач;
поддержка преподавателей и чат;
доступ к материалам на 12 месяцев.

Полная программа курса тут 👈

👉 Остальные курсы
1
📎 Скрытая ловушка в енамках

Метод Enum.TryParse кажется идеальным инструментом для безопасного парсинга строк в enum — он не бросает исключения и возвращает bool, сигнализируя об успехе или неудаче операции.

Но у этого метода есть неочевидное поведение, которое может привести к багам.

Представьте ситуацию: пользователь передаёт статус заказа через API, вы парсите его через TryParse, получаете true, уверенно обрабатываете заказ... и внезапно обнаруживаете в базе статус со значением 999, которого в вашем енаме вообще не существует.

Enum.TryParse возвращает true даже для несуществующих значений enum:
public enum OrderType
{
Cool = 0,
NotCool = 1
}

// Парсим значение, которого НЕТ в enum
Enum.TryParse("999", out OrderType type);
// ✓ Вернёт TRUE
// ✓ day = (OrderType)999
// ✗ Но 999 не определён в OrderType!

Console.WriteLine($"Результат: {type}"); // Вывод: 999


TryParse проверяет только возможность конвертации строки в числовой тип, а не валидность значения для конкретного enum.

Решение

Добавьте проверку через Enum.IsDefined:
if (Enum.TryParse("999", out OrderType type) && 
Enum.IsDefined(typeof(OrderType), type))
{
// Здесь значение гарантированно валидно
} else {
// 999 будет правильно отклонено
}


Enum.IsDefined использует рефлексию и может быть медленным в hot path.

Альтернативы:
// Для hot path: кешируем валидные значения
private static readonly HashSet<OrderType> ValidValues =
new(Enum.GetValues<OrderType>());

public static bool IsValid(OrderType value) =>
ValidValues.Contains(value); // Быстрее IsDefined

// Для непрерывных enum: проверка диапазона
public static bool IsValid(OrderType value) =>
(int)value >= 0 && (int)value <= 1; // Самый быстрый


Microsoft спроектировали это так намеренно, поскольку C# позволяет приводить любое число к типу енамки без ограничений. Это даёт гибкость, но требует от разработчика дополнительной бдительности.

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19🤩122😁2
⭐️ Подборка вакансий для шарпистов

С# разработчик на гибрид в СПБ.

Senior Backend Developer от 250 000 ₽.

Web-разработчик на C# с удалёнкой.

C# / .NET-разработчик на удалёнку.

Бустер — Удалённо (в любом городе мира).

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

🐸 Библиотека шарписта
Please open Telegram to view this post
VIEW IN TELEGRAM
🍩 Донат разработчикам

Microsoft запустили функцию спонсорства на NuGet.org для финансовой поддержки мейнтейнеров пакетов.

Владельцы пакетов добавляют ссылки через раздел "Manage Packages". Пользователи видят кнопку спонсорства и могут поддержать разработчиков напрямую.

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

#async_news
Please open Telegram to view this post
VIEW IN TELEGRAM
👍243🎉3😁2
✏️ Задача с собеса: кинотеатр и лучшие места

В кинотеатр пришли люди, и часть мест уже занята.
Места описаны массивом из нулей и единиц:

1 — место занято
0 — место свободно

Нужно найти такое место, чтобы сидящий оказался как можно дальше от ближайшего соседа.

Разбор решения

Нужно рассмотреть три типа промежутков свободных мест:

• Начало ряда — расстояние до ближайшего соседа = количество нулей
• Конец ряда — расстояние = количество нулей
• Середина — расстояние = количество нулей / 2. Целочисленное деление.

Алгоритм

1. Проходим по массиву один раз
2. Отслеживаем индекс последнего человека, которого мы встретили
3. При встрече человека вычисляем расстояние:

• Если это первый человек → берём его индекс (левый край)
• Если не первый → вычисляем (текущий_индекс - прошлый_индекс) / 2

3. После цикла проверяем правый край: n - 1 - последний_индекс
4. Возвращаем максимум из всех расстояний.

Код:
public class Solution {
public int MaxDistToClosest(int[] seats) {
int n = seats.Length;
int maxDist = 0;
int lastPerson = -1;

for (int i = 0; i < n; i++) {
if (seats[i] == 1) {
if (lastPerson == -1) {
// Левый край
maxDist = i;
} else {
// Середина
maxDist = Math.Max(maxDist, (i - lastPerson) / 2);
}
lastPerson = i;
}
}

// Правый край
maxDist = Math.Max(maxDist, n - 1 - lastPerson);

return maxDist;
}
}


Задача решается одним проходом за линейное время. Главное — правильно обработать три случая: левый край, середину и правый край.

➡️ Попробовать решить

Чтобы щёлкать такие задачи нужно знать алгоритмы. Подтянуть такую базу поможет наш курс по алгоритмам. До конца октября скидка 40%

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

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
📁 Создаём директории правильно

Частая задача: нужно убедиться, что папка существует перед сохранением файла. Многие пишут проверку через Directory.Exists, но есть проще.

Идиоматичный способ:
Directory.CreateDirectory(Path.GetDirectoryName(path)!);


Directory.CreateDirectory идемпотентна — не бросает исключение, если директория уже есть. Метод просто ничего не делает и возвращает DirectoryInfo. Поэтому проверка через Exists избыточна и добавляет лишний вызов файловой системы.

Path.GetDirectoryName может вернуть null для корневых путей или некорректных строк. Поэтому null-forgiving оператор ! используется, когда вы точно знаете, что путь валидный.

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
10
📰 Новости недели

Вспоминаем что произошло в мире за последнее время.

ChatGPT продолжает неудачный додеп

6 ведущих AI-моделей автономно торгуют реальным капиталом на криптовалютных рынках.

Microsoft Agent Framework в вашем .NET AI-чат приложении

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

На одну вакансию теперь 2383 отклика

Microsoft запустили спонсорство для Nuget разрабов

Подборка курсов для повышения скиллов

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

#async_news
Please open Telegram to view this post
VIEW IN TELEGRAM
Опишите разницу между оператором равенства (==) и методом Equals() в C#?

Оператор == и метод Equals() сравнивают два элемента данных типа значения или элемента данных ссылочного типа. Оператор равенства (==) является оператором сравнения, а метод Equals() сравнивает содержимое строки. Оператор == сравнивает ссылочную идентичность, тогда как метод Equals() сравнивает только содержимое.

Библиотека собеса по С#
👍6🌚5🤔3🥱2😁1
🧠 Готовишься к собесам, а ноутбук еле тянет IDE?

Самое время прокачать скиллы и апгрейднуть железо!

Proglib Academy разыгрывает MacBook Pro 14 (M3 Pro, 36 GB, 1 TB SSD) 💻

Купи любой наш курс до 15 ноября → пройди 2 недели обучения → напиши куратору #розыгрыш. Всё, ты в игре!

📚 Среди курсов:

▫️ Алгоритмы и структуры данных — топ для подготовки к собесам в Яндекс и FAANG.

▫️ Архитектуры и шаблоны проектирования — чтобы думать как senior.

▫️ Python, математика для DS, основы IT и другие направления.

👉 Принять участие
😁4
👨‍💻 Три структуры данных, которые игнорируются зря

List<T> — это универсальный солдат C#. Но универсальный не значит оптимальный. Пока вы перебираете 10 000 элементов через .FirstOrDefault(), Dictionary находит нужное за одно обращение. И это только начало.

Queue — когда порядок имеет значение

Обрабатываете задачи по очереди? Вот вам готовое решение:
var tasks = new Queue<UserRequest>();

tasks.Enqueue(new UserRequest { Id = 1, Name = "Alice" });
tasks.Enqueue(new UserRequest { Id = 2, Name = "Bob" });

// Безопасное извлечение (с .NET 6+)
while (tasks.TryDequeue(out var request))
{
await ProcessAsync(request);
}


Первым пришел — первым обработался. Никаких индексов, никаких сортировок.

Stack — для истории действий

Делаете undo/redo или навигацию? Стек решает это из коробки:
var history = new Stack<string>();

history.Push("/home");
history.Push("/products");
history.Push("/cart");

// Вернуться назад
if (history.TryPop(out var lastPage))
{
Console.WriteLine($"Back to: {lastPage}"); // /cart
}


Последнее действие всегда доступно первым. Логика браузерной кнопки «Hазад» готова.

Dictionary — когда нужна скорость

Поиск по ключу за O(1) вместо перебора всего списка:
var users = new Dictionary<int, User>();

users.Add(1, new User { Name = "Alice" });
users.Add(2, new User { Name = "Bob" });

// Безопасная проверка
if (users.TryGetValue(2, out var user))
{
Console.WriteLine(user.Name); // Bob
}


Никаких .FirstOrDefault(x => x.Id == 2) с перебором тысяч записей.

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

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

#il_люминатор
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱2110
💾 Всем фичам фича

Вышло октябрьское обновление 86Box — эмулятора ПК IBM PC. Главное новшество — звуки флоппи-дисководов, записанные с реальных устройств.

Разработчик записал звуки с настоящих 3.5" и 5.25" дисководов. Эмулятор отслеживает активность мотора и головки дисковода в реальном времени и проигрывает соответствующие звуки. Получается достоверная звуковая картина — как будто перед вами настоящее железо из 90-х.

➡️ Полный список изменений

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

#async_news
Please open Telegram to view this post
VIEW IN TELEGRAM
8🤩1🥱1
👨‍💻 6 дней работы

Внимание! Вы проживаете аномальную неделю прямо сейчас. Вся неделя сдвинулась на один день и мы снова проживаем понедельник.

Или у нас будет две пятницы. Учёные ещё не определились.

💬 Как вы? Уже устали или ещё полны энергии?

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

#entry_point
Please open Telegram to view this post
VIEW IN TELEGRAM
4🔥3🥱1
Media is too big
VIEW IN TELEGRAM
Не пропусти МТС True Tech Champ — масштабный фестиваль 21 ноября для тех, кто живет технологиями 🔥

Тебя ждут:

▫️ Захватывающая сюжетная линия. Тебя ждет уникальная кибервселенная с возможностью влиять на ход происходящего.
▫️ Конференция с международными спикерами. Эксперты расскажут о трендах в ИИ и инновациях в индустрии.
▫️ ИТ-качалка. Наращивай экспертизу на воркшопах.
▫️ Шоу-финал ИТ-чемпионата. Более 250 талантов со всей России сразятся в лайв-кодинге и программировании роботов на скоростное прохождение лабиринтов со спецэффектами. Выбирай и болей за фаворитов.
▫️ Айтивности. Тебя ждут бои роботов, кодерские челленджи, пайка плат и не только. Заработай True Coins и обменяй их на стильный мерч.
▫️ HR-Hub. Команда МТС расскажет о возможностях для развития в компании и поможет перезагрузить карьерный трек.
▫️ Афтепати со звездными хэдлайнерами. Зажги под популярные хиты.

Когда: 21 ноября, МТС Live Холл в Москве и онлайн.

Регистрируйся на сайте. Участие бесплатно, количество мест ограничено.
🤩 Как взять последние символы строки в C#

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

Для получения последних 10 символов используется оператор диапазона:
var last10 = text[^10..];


Такой способ делает код короче и легче для чтения.
Но есть один момент — если строка короче десяти символов, программа выбросит ошибку.
Чтобы этого избежать, добавьте проверку:
var last10 = text.Length >= 10 ? text[^10..] : text;


Теперь код работает безопасно даже с короткими строками.

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
13🥱3🌚2👾2
🎁 Конкурс от Proglib Academy!

Кстати, если кто-то ещё не в курсе — у нас тут раздают MacBook Pro 14.
Да-да, не шутка, настоящий, железный, с M3 Pro

Но! Чтобы успеть пройти 2 недели обучения к 15 ноября, курс нужно взять до конца октября — и сейчас на всё скидка 40%.

Чтобы поучаствовать, нужно:

1️⃣ Покупаешь любой курс до конца октября;
2️⃣ Проходишь 2 недели обучения к 15 ноября;
3️⃣ Написать куратору в чат #розыгрыш.

До 15 ноября, потом всё — поезд (и макбук) уйдёт.

👉 Участвовать в розыгрыше
2
⚡️ Deadlock в EF Core: как предотвратить

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

В итоге SQL Server прерывает одну из транзакций:
SqlException: Transaction (Process ID xx) was deadlocked on resources...


Пример простого дедлока: два контекста одновременно меняют одну строку и пытаются сохранить изменения. Один запрос блокирует строку, второй вызывает дедлок.
await using var context1 = new AppDbContext();
await using var context2 = new AppDbContext();

var order1 = await context1.Orders.FindAsync(1);
var order2 = await context2.Orders.FindAsync(1);

order1.Status = "Paid";
order2.Status = "Shipped";

await context1.SaveChangesAsync(); // Блокирует строку
await context2.SaveChangesAsync(); // Возможен deadlock


Стратегии предотвращения

• Короткие транзакции

Минимизируйте работу внутри транзакции:
await using var tx = await context.Database.BeginTransactionAsync();
var order = await context.Orders.FindAsync(orderId);
order.Status = "Paid";
await context.SaveChangesAsync();
await tx.CommitAsync();


Избегайте сетевых вызовов и посторонних запросов перед коммитом.

• Правильные индексы

Отсутствие индексов приводит к сканированию таблиц и длительным блокировкам. Используйте SQL Profiler для мониторинга.

• Оптимальный уровень изоляции

ReadCommitted обычно достаточен для большинства операций:
await using var tx = await context.Database.BeginTransactionAsync(
IsolationLevel.ReadCommitted);


• Логика повторов

Используйте встроенную политику retry в EF Core:
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(connectionString, sql =>
sql.EnableRetryOnFailure(
maxRetryCount: 3,
maxRetryDelay: TimeSpan.FromSeconds(5),
errorNumbersToAdd: null)));


• RowVersion для контроля конкурентности

public class Order
{
public int Id { get; set; }
public string Status { get; set; }

[Timestamp]
public byte[] RowVersion { get; set; }
}


EF Core выбросит DbUpdateConcurrencyException при конфликте изменений.

Дедлоки не баги, а следствие паттернов конкурентного доступа.

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
6👍5
C#-навигация прямо в браузере? Да, теперь и такое есть! 👀

Для тех, кто работает с C#, приятные новости от SourceCraft. Платформа добавила умную навигацию, которая понимает связи между функциями и позволяет переходить по объявлениям прямо в веб-интерфейсе — как в вашей любимой IDE. 🔥

А ИИ-ассистент теперь дописывает методы на C# не изолированно, а в контексте всего проекта. Для команд с разнесёнными код-ревью или для быстрого онбординга новичков — просто находка. Можно даже коммитить правки из браузера, не теряя типизацию.
🤔6👍3
Повышение надёжности .NET-приложений: как обрабатывать сбои и предотвращать каскадные ошибки.

Даже самые стабильные системы ломаются — вопрос лишь в том, насколько вы готовы к этому. Библиотека Polly позволяет гибко управлять сбоями и повышать устойчивость микросервисов и API.

На открытом вебинаре курса OTUS C# ASP.NET Core разработчик Виктор Дзицкий покажет, как использовать Polly и HttpClientFactory для защиты приложений от временных отказов и непредсказуемых сетевых ошибок.

📌 6 ноября, 20:00
Повышение надежности .NET-приложений с Polly
— ключевые стратегии и политики Polly
— настройка и комбинирование стратегий для сложных сценариев
— защита от каскадных сбоев и готовые паттерны устойчивости
— улучшения в .NET 8

Вебинар бесплатный и подойдёт .NET-разработчикам, работающим с микросервисами и внешними API, которые хотят сделать свои системы по-настоящему отказоустойчивыми.

👉 Регистрируйтесь: https://clc.to/zyj9ow

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru