Библиотека шарписта | 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