Библиотека шарписта | C#, F#, .NET, ASP.NET
Все самое полезное для C#-разработчика в одном канале. По рекламе: @proglib_adv Учиться у нас: https://proglib.io/w/b60af5a4 Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead
Show more📈 Analytical overview of Telegram channel Библиотека шарписта | C#, F#, .NET, ASP.NET
Channel Библиотека шарписта | C#, F#, .NET, ASP.NET (@csharpproglib) in the Russian language segment is an active participant. Currently, the community unites 21 865 subscribers, ranking 6 209 in the Technologies & Applications category and 30 824 in the Russia region.
📊 Audience metrics and dynamics
Since its creation on невідомо, the project has demonstrated rapid growth, gathering an audience of 21 865 subscribers.
According to the latest data from 11 June, 2026, the channel demonstrates stable activity. Although there has been a change in the number of participants by -95 over the last 30 days and by -6 over the last 24 hours, overall reach remains high.
- Verification status: Not verified
- Engagement rate (ER): The average audience engagement rate is 12.48%. Within the first 24 hours after publication, content typically collects 7.13% reactions from the total number of subscribers.
- Post reach: On average, each post receives 2 729 views. Within the first day, a publication typically gains 1 560 views.
- Reactions and interaction: The audience actively supports content: the average number of reactions per post is 9.
- Thematic interests: Content is focused on key topics such as .net, шарписта, навигация, await, string.
📝 Description and content policy
The author describes the resource as a platform for expressing subjective opinions:
“Все самое полезное для C#-разработчика в одном канале.
По рекламе: @proglib_adv
Учиться у нас: https://proglib.io/w/b60af5a4
Для обратной связи: @proglibrary_feeedback_bot
РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead”
Thanks to the high frequency of updates (latest data received on 12 June, 2026), the channel maintains relevance and a high level of publication reach. Analytics show that the audience actively interacts with content, making it an important point of influence in the Technologies & Applications category.
public class MyService
{
private readonly MySettings _settings;
public MyService(IOptions<MySettings> options)
{
_settings = options.Value;
}
public void PrintSettings()
{
Console.WriteLine($"API Key: {_settings.ApiKey}");
}
}
Это подходит для статичных настроек, которые не меняются во время работы приложения.
IOptionsSnapshot — создаётся на каждый запрос или скоуп и предоставляет новые значения при каждом новом запросе:
public class MyScopedService
{
private readonly MySettings _settings;
public MyScopedService(IOptionsSnapshot<MySettings> options)
{
_settings = options.Value;
}
public void PrintSettings()
{
Console.WriteLine($"Timeout: {_settings.Timeout}");
}
}
Подходит для веб-приложений, где конфигурация может меняться между запросами.
IOptionsMonitor — позволяет подписаться на изменения и получать обновления конфигурации в реальном времени:
public class MyMonitorService
{
private MySettings _settings;
public MyMonitorService(IOptionsMonitor<MySettings> monitor)
{
_settings = monitor.CurrentValue;
monitor.OnChange(updatedSettings =>
{
_settings = updatedSettings;
Console.WriteLine("Settings updated!");
});
}
public void PrintSettings()
{
Console.WriteLine($"LogLevel: {_settings.LogLevel}");
}
}
Подходит для длительно работающих приложений, которые должны реагировать на изменения конфигурации без перезапуска.
🐸Библиотека шарписта
#sharp_viewvar text = WaffleEngine.Html(paragraphs: 2, includeHeading: true);
var text = WaffleEngine.Text(paragraphs: 1, includeHeading: true);
var markdown = WaffleEngine.Markdown(paragraphs: 1, includeHeading: true);
Поддерживает три формата: HTML, обычный текст и Markdown.
➡️ Попробовать либу
🐸Библиотека шарписта
#sharp_viewif (counts.ContainsKey(key))
counts[key]++;
else
counts[key] = 1;
Но есть способ проще:
counts[key] = counts.GetValueOrDefault(key) + 1;
Метод GetValueOrDefault возвращает значение, если ключ есть, или значение по умолчанию (для int это 0). Затем добавляем единицу. Никаких условных операторов, одна строка.
Если можете — используйте LINQ:
var counts = items.GroupBy(x => x.Key)
.ToDictionary(g => g.Key, g => g.Count());
Это явно показывает намерение: группируем по ключу, считаем количество в каждой группе.
Но если вы наполняете словарь в цикле или обрабатываете поток данных, GetValueOrDefault — идеальный выбор.
🐸Библиотека шарписта
#sharp_view<>c__DisplayClass2_0, d__5``1.MoveNext() и прочих артефактов, которые сгенерировал компилятор. Это не ошибка — это просто то, как .NET преобразует современный C# в IL. Но это делает поиск проблемы медленнее, чем нужно.
Demystifier восстанавливает оригинальный вид кода:
• Вместо ValueTuple``2 param показывает (string val, bool) param
• Вместо Func``1 показывает Func<string>
• async методы помечает как async Task<string>
• Локальные функции и лямбды показывает с контекстом
Как применить
Вызовите exception.Demystify() и передайте результат:
try { /* ваш код */ }
catch (Exception ex)
{
logger.LogError(ex.Demystify(), "Ошибка");
}
Анализ стека стоит ресурсов. На высоконагруженной системе вызывать Demystify для каждого исключения неэкономно. Используйте его выборочно — для критических путей, для отладки в development окружении или для редких, но важных ошибок.
➡️ Репозиторий либы
🐸Библиотека шарписта
#sharp_viewIActionResult без типов.
Проблема с IActionResult:
[HttpGet("{id:guid}")]
public async Task<IActionResult> GetById(Guid id, ISender mediator, CancellationToken ct)
{
var dto = await mediator.Send(new GetUserQuery(id), ct);
return dto is null ? NotFound() : Ok(dto);
}
Возвращаемый тип — IActionResult. Просто интерфейс. Ничего конкретного. Кто читает этот код, не знает, что именно вернётся. Может быть UserDto, может быть ошибка, может быть что угодно.
Вот так выглядит сгенерированная Swagger документация:
{
"responses": {
"200": { "description": "Success" }
}
}
Никакой информации о схеме. Кто использует ваш API, не знает, какие поля будут в ответе. IDE не может подсказать структуру. Тесты пишутся вслепую.
Решение: ActionResult<T>
[HttpGet("{id:guid}")]
public async Task<ActionResult<UserDto>> GetById(Guid id, ISender mediator, CancellationToken ct)
{
var dto = await mediator.Send(new GetUserQuery(id), ct);
return dto is null ? NotFound() : Ok(dto);
}
Возвращаемый тип — ActionResult<UserDto>. Конкретно и ясно. Читающий код понимает мгновенно: метод возвращает UserDto при успехе или ошибку. Swagger генератор видит типы и строит правильную документацию.
IActionResult можно использовать, когда метод не возвращает тело, к примеру ответ 204.
🐸Библиотека шарписта
#sharp_viewstatic с изменяемым состоянием. Удобно? Да. Безопасно? Совсем нет.
Почему static плохо сочетается с данными
Static — это ключевое слово, которое любят новички и используют для удобства. А потом из этого вырастают проблемы, которые отъедают часы отладки. Главная беда в том, что статические поля существуют всё время работы программы и доступны отовсюду.
Четыре золотых правила
1. Статические поля могут быть только для чтения. Лучше — константы.
2. Статические методы должны работать как математические функции: дали параметры — получили результат. Никаких побочных эффектов, никаких изменений состояния. Например: Select, Where, First из LINQ — это всё статические методы расширения, которые не трогают исходную последовательность.
3. Если в классе есть методы, которые не используют поля экземпляра, эту логику лучше вынести в отдельный статический класс-помощник. Это делает код чище, тесты проще.
4. Если вы создаёте статическое поле, пусть оно указывает на что-то, что не меняется. На объект конфигурации? Хорошо. На список данных, который вы потом модифицируете? Катастрофа.
Когда static — ваш друг
• Вспомогательные классы с чистыми функциями
Создайте статический класс StringUtils с методом static string ToPascalCase(string input). Нет состояния, нет побочных эффектов, нет проблем. Это хорошее использование.
• Методы расширения для преобразований
Select, Where и компания — статические методы расширения, которые берут данные, преобразуют их и возвращают новые. Функциональный подход, никакого волшебства.
• ThreadStatic для действительно отдельного состояния
Если каждому потоку нужно своё состояние, можно использовать ThreadStatic. Но даже здесь нужна осторожность — каждый поток всё равно должен управлять своим состоянием.
Передайте зависимость через конструктор, используйте DI-контейнер, создайте объект на сессию. Ваш будущий я, сидящий в отладчике в три утра, скажет вам спасибо.
🐸Библиотека шарписта
#il_люминаторdotnet --info, она покажет версии SDK и рантаймов и архитектуру хоста.
Сборка проекта выполняется командой dotnet build, по умолчанию в конфигурации Debug и с выводом артефактов в bin, причем команда учитывает инкрементальные изменения для скорости.
Запуск приложения через dotnet run объединяет сборку и старт процесса, что эквивалентно кнопке Run в IDE и удобно для ручных проверок локально.
Горячая перезагрузка из терминала через dotnet watch отслеживает изменения файлов и повторно запускает приложение с Hot Reload без ручного рестарта, что ускоряет цикл правка и проверка.
Если сборка ведет себя странно, стоит выполнить dotnet clean, чтобы удалить выходные артефакты и заставить следующий build собрать все заново.
Для развертывания используйте dotnet publish, который соберет релиз и положит готовый к деплою набор файлов в папку publish, включая веб приложения и сервисы.
🐸Библиотека шарписта
#sharp_view(int)Math.Sqrt(num) * (int)Math.Sqrt(num) == numНо на собесе после этого последует вопрос: «А можете без встроенной функции?» Вот тогда начинается интересное. Вместо математики используем логику: если x * x = num, то x находится где-то между 1 и num. Сужаем диапазон поиска, пока не найдём точный ответ.
public bool IsPerfectSquare(int num)
{
long left = 1;
long right = num;
while (left <= right)
{
long mid = (left + right) / 2;
long square = mid * mid;
if (square == num)
return true;
else if (square < num)
left = mid + 1;
else
right = mid - 1;
}
return false;
}
Есть ещё метод Ньютона для поиска корня — он даже быстрее для больших чисел:public bool IsPerfectSquare(int num)
{
long x = num;
while (x * x > num)
{
x = (x + num / x) / 2;
}
return x * x == num;
}
Главное: объясните почему вы выбрали именно этот подход, а не просто скопировали решение. На собесе вас оценивают не только по скорости, а по способности мыслить.
➡️ Попробовать решить
🐸Библиотека шарписта
#dotnet_challenge
Available now! Telegram Research 2025 — the year's key insights 
