Библиотека шарписта | C#, F#, .NET, ASP.NET
Все самое полезное для C#-разработчика в одном канале. Наши курсы: https://clc.to/y3LDtw По рекламе: @proglib_adv Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead
Больше📈 Аналитический обзор Telegram-канала Библиотека шарписта | C#, F#, .NET, ASP.NET
Канал Библиотека шарписта | C#, F#, .NET, ASP.NET (@csharpproglib) языкового сегмента Русский является активным участником. Сейчас сообщество объединяет 21 701 подписчиков, занимая 5 943 место в категории Технологии и приложения и 30 267 место в регионе Россия.
📊 Показатели аудитории и динамика
С момента создания невідомо проект демонстрирует стремительный рост, собрав аудиторию из 21 701 подписчиков.
Согласно последним данным от 29 августа, 2026, канал показывает стабильную активность. За последние 30 дней изменение числа участников составило -48, а за последние 24 часа — -6, при этом общий охват остаётся высоким.
- Статус верификации: Не верифицирован
- Уровень вовлечённости (ER): Средний показатель вовлечённости аудитории составляет 16.72%. В первые 24 часа после публикации контент обычно набирает 7.84% реакций от общего числа подписчиков.
- Охват публикаций: В среднем каждый пост получает 3 628 просмотров. В течение первых суток публикация набирает 1 702 просмотров.
- Реакции и взаимодействия: Аудитория активно поддерживает контент: среднее количество реакций на один пост — 23.
- Тематические интересы: Контент сосредоточен на ключевых темах, таких как .net, шарписта, навигация, await, string.
📝 Описание и контентная политика
Автор описывает ресурс как площадку для выражения субъективного мнения:
“Все самое полезное для C#-разработчика в одном канале.
Наши курсы: https://clc.to/y3LDtw
По рекламе: @proglib_adv
Для обратной связи: @proglibrary_feeedback_bot
РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead”
Благодаря высокой частоте обновлений (последние данные получены 30 августа, 2026) канал поддерживает актуальность и высокий уровень охвата публикаций. Аналитика показывает, что аудитория активно взаимодействует с контентом, что делает его важной точкой влияния в категории Технологии и приложения.
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
Directory.CreateDirectory идемпотентна — не бросает исключение, если директория уже есть. Метод просто ничего не делает и возвращает DirectoryInfo. Поэтому проверка через Exists избыточна и добавляет лишний вызов файловой системы.
Path.GetDirectoryName может вернуть null для корневых путей или некорректных строк. Поэтому null-forgiving оператор ! используется, когда вы точно знаете, что путь валидный.
🐸 Библиотека шарписта
#sharp_viewpublic 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_challengeTryParse, получаете 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_viewif (string.IsNullOrEmpty(...)) была ежедневной рутиной:
public void ProcessUser(string name, string email, int age)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentException("Value cannot be null or empty.", nameof(name));
if (string.IsNullOrEmpty(email))
throw new ArgumentException("Value cannot be null or empty.", nameof(email));
if (age < 0)
throw new ArgumentOutOfRangeException(nameof(age), "Value must be non-negative.");
// Наконец-то бизнес-логика!
}
Код становился шумным, а реальная логика терялась в океане проверок. Каждый разработчик писал по-своему, сообщения об ошибках отличались, а про опечатки в nameof() вообще молчим.
Теперь всё это превращается в лаконичные однострочники:
public void ProcessUser(string name, string email, int age)
{
ArgumentException.ThrowIfNullOrEmpty(name);
ArgumentException.ThrowIfNullOrEmpty(email);
ArgumentOutOfRangeException.ThrowIfNegative(age);
}
Стандартная библиотека предлагает методы на все случаи жизни:
// Проверки на null
ArgumentNullException.ThrowIfNull(user);
// Числовые диапазоны
ArgumentOutOfRangeException.ThrowIfNegative(temperature);
ArgumentOutOfRangeException.ThrowIfZero(divisor);
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(count);
// Сравнения
ArgumentOutOfRangeException.ThrowIfGreaterThan(progress, 100);
ArgumentOutOfRangeException.ThrowIfLessThan(quantity, 1);
ArgumentOutOfRangeException.ThrowIfEqual(status, Status.Invalid);
ArgumentOutOfRangeException.ThrowIfNotEqual(version, expectedVersion);
Эти методы — не просто синтаксический сахар. Они воплощают принцип fail-fast: обнаруживай проблемы немедленно, не позволяй невалидным данным распространяться по системе.
🐸 Библиотека шарписта
#sharp_viewpublic delegate void NotifyHandler(string message);
NotifyHandler handler = LogToConsole;
handler += SendEmail;
handler += SaveToDatabase;
handler("Пользователь авторизовался");
Когда вы вызовете handler, все три метода выполнятся последовательно. Именно эта возможность называется мультикаст.
Основной сценарий — реализация паттерна Observer без лишних сложностей. Вы подписываете несколько обработчиков на одно событие, и все они получают уведомление.
Важные детали
• Методы вызываются в том порядке, в котором вы их добавили. Но полагаться на конкретный порядок — плохая практика. Ваши обработчики должны быть независимыми.
• Если делегат возвращает значение, вы получите результат только от последнего метода в цепочке.
• Если один из методов выбросит исключение, остальные не выполнятся.
🐸 Библиотека шарписта
#sharp_viewIQueryable<Order> query = context.Orders;
query = sortBy switch
{
"total_asc" => query.OrderBy(o => o.TotalAmount),
"total_desc" => query.OrderByDescending(o => o.TotalAmount),
"date_asc" => query.OrderBy(o => o.CreatedAt),
"date_desc" => query.OrderByDescending(o => o.CreatedAt),
// ещё 20 полей...
};
С динамической сортировкой код становится лаконичным:
var orders = context.Orders
.Where(o => o.Status == OrderStatus.Completed)
.OrderByDynamic("TotalAmount DESC")
.ThenByDynamic("CreatedAt ASC");
Имя поля и направление сортировки передаются строкой. Всё остается IQueryable — запрос уходит в базу, а не выполняется в памяти.
Можно комбинировать несколько уровней сортировки, передавая массив строк от клиента.
Если строка сортировки приходит от пользователя, нужна валидация. Иначе можно получить exception на несуществующем поле или, хуже, уязвимость.
🐸 Библиотека шарписта
#sharp_viewЦены: [7, 1, 5, 3, 6, 4] Ответ: 7Покупаем за 1, продаём за 5 (прибыль 4). Покупаем за 3, продаём за 6 (прибыль 3). Итого — 7. Алгоритм Самый простой подход — жадный алгоритм. Если завтра цена выше, чем сегодня — покупаем сегодня и продаём завтра. Собираем прибыль с каждого роста цены. Представьте график цен: вам нужно получить прибыль со всех участков, где график идёт вверх. Неважно, сколько это будет сделок — каждый рост приносит деньги. Почему это работает Если цена растёт три дня подряд (например, 1 → 3 → 5), то неважно, продавать ли каждый день или держать до конца. Код:
public class Solution
{
public int MaxProfit(int[] prices)
{
if (prices == null || prices.Length < 2)
return 0;
int totalProfit = 0;
for (int i = 1; i < prices.Length; i++)
{
// Если цена выросла — берём эту прибыль
if (prices[i] > prices[i - 1])
{
totalProfit += prices[i] - prices[i - 1];
}
}
return totalProfit;
}
}
Или ещё компактнее:
public class Solution
{
public int MaxProfit(int[] prices)
{
int profit = 0;
for (int i = 1; i < prices.Length; i++)
{
profit += Math.Max(0, prices[i] - prices[i - 1]);
}
return profit;
}
}
Жадный подход здесь безупречен: захватываем каждый рост, игнорируем падения. Никаких сложных расчётов оптимальных точек — только простая логика и максимальная прибыль.
➡️ Попробовать решить
Чтобы щёлкать такие задачи нужно знать алгоритмы. Подтянуть такую базу поможет наш курс по алгоритмам. До конца октября скидка 40%
🐸 Библиотека шарписта
#dotnet_challenge