ch
Feedback
Библиотека шарписта | C#, F#, .NET, ASP.NET

Библиотека шарписта | C#, F#, .NET, ASP.NET

前往频道在 Telegram

Все самое полезное для 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 707 名订阅者,在 技术与应用 类别中位列第 5 962,并在 俄罗斯 地区排名第 30 301

📊 受众指标与增长动态

невідомо 创建以来,项目保持高速增长,吸引了 21 707 名订阅者。

根据 27 八月, 2026 的最新数据,频道保持稳定运转。过去 30 天订阅人数变化为 -42,过去 24 小时变化为 3,整体触达仍然可观。

  • 认证状态: 未认证
  • 互动率 (ER): 平均受众互动率为 15.91%。内容发布后 24 小时内通常能获得 7.92% 的反应,占订阅者总量。
  • 帖子覆盖: 每篇帖子平均可获得 3 454 次浏览,首日通常累积 1 718 次浏览。
  • 互动与反馈: 受众积极参与,单帖平均反应数为 26
  • 主题关注点: 内容集中在 .net, шарписта, навигация, await, string 等核心主题上。

📝 描述与内容策略

作者将该频道定位为表达主观观点的平台:
Все самое полезное для C#-разработчика в одном канале. Наши курсы: https://clc.to/y3LDtw По рекламе: @proglib_adv Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead

凭借高频更新(最新数据采集于 28 八月, 2026),频道始终保持新鲜度与高覆盖。分析显示受众积极互动,使其成为 技术与应用 类别中的关键影响点。

21 707
订阅者
+324 小时
-137
-4230
帖子存档
🔄 Дайджест недели Коротко про события недели. — Microsoft разрабатывает функцию перемещения панели задач в Windows 11 Функци
🔄 Дайджест недели Коротко про события недели. — Microsoft разрабатывает функцию перемещения панели задач в Windows 11 Функция ожидается летом 2026 года как часть усилий по улучшению репутации ОС. — Linux 6.19Превью .NET 11Бустим рабочее место за 10 шагов 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #async_news

📎 Пропущенный аудит Метод ExecuteUpdate в EF Core ускоряет массовые обновления, но пропускает перехватчики и события SaveChanges. Это может сломать аудит изменений. Перехватчик SaveChanges ловит изменения из трекера. Но ExecuteUpdate работает напрямую с БД и игнорирует его:
public override async Task<int> SaveChangesAsync(CancellationToken ct = default)
{
    // Захватывает изменения от SaveChanges
    var entries = ChangeTracker.Entries()
        .Where(e => e.State == EntityState.Modified);
    
    // Но не от ExecuteUpdate!
}
Решение через ручной аудит Добавляйте аудит вручную перед или после ExecuteUpdate:
await context.Products
    .Where(p => p.CategoryId == categoryId)
    .ExecuteUpdateAsync(s => s
        .SetProperty(p => p.Price, newPrice)
        .SetProperty(p => p.ModifiedAt, DateTime.UtcNow)
        .SetProperty(p => p.ModifiedBy, currentUser));

// Отдельная запись аудита
context.AuditLogs.Add(new AuditLog
{
    Action = "BulkPriceUpdate",
    EntityType = "Product",
    Details = $"Обновил CategoryId={categoryId}, цена={newPrice}"
});
await context.SaveChangesAsync();
Альтернативы для полного аудита • Триггеры на уровне БД ловят все изменения, включая ExecuteUpdate. Минус — сложнее тестировать и отлаживать. • Библиотеки расширения EF предлагают BulkUpdate с встроенным аудитом через опции UseAudit. 📍 Навигация: ВакансииЗадачиСобесы 🐸Библиотека шарписта #sharp_view

⚡️ C# убил Builder для простых случаев Target-typed new убирает дублирование типов при инициализации, а with-выражения делают иммутабельные обновления одной строкой кода. Раньше при создании объекта приходилось дважды писать тип: var user = new UserDto { ... }. Теперь достаточно User user = new() { ... }. Компилятор выводит тип из контекста — при возврате из методов, в параметрах, элементах коллекций Работа с иммутабельными объектами традиционно требовала copy-конструкторов, Builder'а или AutoMapper. with-выражение создаёт поверхностную копию с изменением указанных свойств: var updated = user with { Age = 31 }. Компилятор генерирует код копирования автоматически. 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #sharp_view

Собираем фулл-хаус: 3 курса по цене 1 Хватит выбирать между «полезно», «модно» и «для души». Мы запустили механику, которая п
Собираем фулл-хаус: 3 курса по цене 1 Хватит выбирать между «полезно», «модно» и «для души». Мы запустили механику, которая позволяет собрать кастомный стек навыков без удара по бюджету: покупаете один курс — два других забираете бесплатно. В Enterprise ценится фундаментальность. Углубитесь в архитектуру и шаблоны проектирования для построения сложных систем или подтяните алгоритмы и структуры данных для технических интервью. Для тех, кто хочет понимать математику ML-моделей (вне зависимости от языка) — полный набор по AI: от линала и ML-старта до разработки автономных агентов. Ну и классика: обновлённый Python как второй язык для скриптов. Собрать свой пак

👨‍💻 Span<T> как ref struct Разбираем вопрос с собеса, в этот раз про Span. Span<T> даёт доступ к памяти без копий и аллокаций. Но почему его сделали ref struct с кучей запретов, и когда лучше взять Memory<T>? Ответ лежит в нашем канале с вопросами с собесов 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #dotnet_challenge

🧑‍💻 Когда чистый код всё равно требует комментариев Чистый код делает программу понятной без лишних объяснений. Но иногда к
🧑‍💻 Когда чистый код всё равно требует комментариев Чистый код делает программу понятной без лишних объяснений. Но иногда комментарии необходимы, чтобы передать суть решений, которые не уместить в самих строках. Роберт Мартин в книге «Чистый код» не запрещает комментарии полностью. Он против тех, что дублируют очевидное или устаревают со временем. Когда комментарии спасают ситуацию • Сложная логика или хак:
// Обход бага в IE11 с обработкой форм
if (isIE11()) {
    polyfillFormSubmit();
}
• Предупреждения о рисках:
// Не трогать: изменение сломает кэш в проде до деплоя новой версии
cache.invalidateOnlyOnRestart();
• Указание на патенты, стандарты или тикеты в баг-трекере. 💬 Когда, по вашему мнению, ещё могут пригодиться комментарии в коде 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #il_люминатор

📂 File-Scoped Namespaces Cинтаксис file-scoped namespaces заменяет привычное объявление пространства имён со скобками на одн
📂 File-Scoped Namespaces Cинтаксис file-scoped namespaces заменяет привычное объявление пространства имён со скобками на однострочное с точкой с запятой. Раньше каждый файл в C# проекте начинался с namespace MyApp.Services { ... }, что добавляло один уровень отступа ко всему коду внутри. Теперь достаточно написать namespace MyApp.Services; в начале файла, и всё содержимое автоматически находится в этом пространстве имён без дополнительной вложенности. Код становится более плоским. Вместо того чтобы начинать каждый класс с двух уровней отступа: namespace + class, вы сразу работаете с одним. При рефакторинге, когда нужно переместить класс в другой namespace, старый подход требовал изменения строки с объявлением. В git diff это выглядело как замена всего файла, даже если логика класса не менялась. C новым подходом меняется только одна строка вверху. Компилятор не видит разницы — это чисто синтаксический сахар. IL-код идентичен, производительность не меняется. 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #sharp_view

🧑‍💻 Композиция функций в C# Функциональное программирование — не просто академическая теория. Это парадигма, превращающая императивный спагетти-код в декларативные, тестируемые и поддерживаемые решения. Проблема императивного кода:
// Традиционный подход - может быть трудно читать и сложно тестировать
public OrderDto ProcessOrder(int orderId)
{
    var order = _dbContext.Orders.Find(orderId);
    if (order == null) throw new NotFoundException();
    
    if (order.Status != "Pending") 
        throw new InvalidOperationException();
    
    var customer = _dbContext.Customers.Find(order.CustomerId);
    if (!customer.IsActive) 
        throw new InvalidOperationException();
    
    var discount = customer.IsVip ? 0.1m : 
                   order.Total > 1000 ? 0.05m : 0m;
    
    order.FinalTotal = order.Total * (1 - discount);
    _dbContext.SaveChanges();
    
    return new OrderDto { ... };
}
Проблемы: смешанные обязанности, жёсткая связанность с БД, невозможность переиспользования, хрупкость при изменениях. Композиционное решение:
public class OrderProcessingPipeline
{
    private readonly Func<int, Task<Order?>> _loadOrder;
    private readonly Func<Order, Task<Customer?>> _loadCustomer;
    
    public async Task<Result<OrderDto, Error>> ProcessAsync(int orderId)
    {
        return await Result<Order, Error>
            .FromNullable(await _loadOrder(orderId), Error.OrderNotFound)
            .BindAsync(_loadCustomer)
            .BindAsync(_validateStatus)
            .BindAsync(_calculateDiscount)
            .BindAsync(_persistOrder)
            .MapAsync(_mapToDto);
    }
}
Преимущества: единственная ответственность каждой функции, простота тестирования, композируемость, декларативный флоу. Основа композиции — чистые функции без побочных эффектов:
public static class PricingFunctions
{
    public static decimal CalculateDiscount(CustomerType type, decimal total) => 
        type switch
        {
            CustomerType.Vip => total * 0.15m,
            CustomerType.Premium => total * 0.10m,
            _ => 0m
        };
    
    public static decimal ApplyTax(decimal amount, decimal rate) => 
        amount * (1 + rate);
    
    // Композиция
    public static Func<CustomerType, decimal, decimal> CalculateFinalPrice => 
        (type, total) => ApplyTax(total - CalculateDiscount(type, total), 0.08m);
}
Тест такой функции:
[Theory]
[InlineData(CustomerType.Vip, 1000, 918.00)]
public void CalculateFinalPrice_ReturnsExpected(CustomerType type, decimal total, decimal expected)
{
    Assert.Equal(expected, PricingFunctions.CalculateFinalPrice(type, total));
}
Начните с малого: замените один цикл на Map, один if/throw на Result. Паттерны быстро станут естественными, и ваша кодовая база скажет спасибо. 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #il_люминатор

🌼 Бустим рабочее место за 10 шагов Удаленка — это не только про свободу выбора места работы, но и про умение создать условия
+5
🌼 Бустим рабочее место за 10 шагов Удаленка — это не только про свободу выбора места работы, но и про умение создать условия для продуктивности. ➡️ В карточках 5 советов по обустройству рабочего места, а остальные в статье. 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта

📂 File-Scoped Namespaces Cинтаксис file-scoped namespaces заменяет привычное объявление пространства имён со скобками на одн
📂 File-Scoped Namespaces Cинтаксис file-scoped namespaces заменяет привычное объявление пространства имён со скобками на однострочное с точкой с запятой. Раньше каждый файл в C# проекте начинался с namespace MyApp.Services { ... }, что добавляло один уровень отступа ко всему коду внутри. Теперь достаточно написать namespace MyApp.Services; в начале файла, и всё содержимое автоматически находится в этом пространстве имён без дополнительной вложенности. Код становится более плоским. Вместо того чтобы начинать каждый класс с двух уровней отступа: namespace + class, вы сразу работаете с одним. При рефакторинге, когда нужно переместить класс в другой namespace, старый подход требовал изменения строки с объявлением. В git diff это выглядело как замена всего файла, даже если логика класса не менялась. C новым подходом меняется только одна строка вверху. Компилятор не видит разницы — это чисто синтаксический сахар. IL-код идентичен, производительность не меняется. 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #sharp_view

📷 Подборка вакансий для шарпистов C#/.NET разработчик — 265 000 ₽. Удалёнка Middle/Senior .NET Developer — от 3 000 до 3 500 $. Удалёнка C#/.NET-разработчик — Удалёнка ➡️ Еще больше топовых вакансий — в нашем канале C# Jobs 🐸 Библиотека шарписта

⚡️ Почему IQueryable не должен покидать слой данных Разработчики используют EF Core и передают IQueryable по всему приложению, считая это эффективным подходом. Но такая практика создаёт серьёзные проблемы с архитектурой и сопровождением кода. IQueryable позволяет строить динамические SQL-запросы, выполняя фильтрацию на стороне БД, а не в памяти приложения:
var startDate = new DateTime(2023, 1, 1);

// Плохо: загружаем всё в память, затем фильтруем
var allRecords = context.Purchases.ToList();
var filtered = allRecords.Where(p => p.Date > startDate).ToList();

// Хорошо: фильтрация выполняется базой данных
var filtered = context.Purchases
    .Where(p => p.Date > startDate)
    .ToList();
Второй подход быстрее и эффективнее. Но когда IQueryable начинает путешествовать через слои приложения, возникают проблемы. Антипаттерн: распространение IQueryable. Типичный сценарий — IQueryable передаётся через слои:
// Репозиторий
public class PurchaseRepository
{
    public IQueryable<Purchase> GetAll() => 
        _context.Purchases.AsQueryable();
}

// Сервис бизнес-логики
public class PurchaseService
{
    public IQueryable<Purchase> GetActive() => 
        _repository.GetAll().Where(p => p.Status == "Active");
}

// Контроллер
var userPurchases = _service.GetActive()
    .Where(p => p.UserId == currentUserId);

// Представление
@foreach(var item in Model.Where(p => p.IsCompleted)) 
{
    <!-- рендеринг -->
}
Проблемы: • Логика доступа к данным размазана по всему приложению • Нарушен принцип единственной ответственности • IQueryable наследует IEnumerable — код может не знать, что работает с запросом к БД • Исключения в runtime, если EF не может преобразовать код в SQL • Сложное тестирование и отладка Решить эти проблемы можно, к примеру, паттерном спецификация, или, если спецификации избыточны, передавайте выражения:
public interface IPurchaseRepository
{
    Task<List<Purchase>> FindAsync(Expression<Func<Purchase, bool>> predicate);
}

// Использование
var purchases = await _repository.FindAsync(
    p => p.IsCompleted && p.UserId == currentUserId);
Запрос по-прежнему выполняется в БД, но логика доступа к данным инкапсулирована. 💬 Как бы вы решили эту проблему 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #sharp_view

🤩 Свежее превью .NET Microsoft выпустила первую предварительную версию .NET 11 с улучшениями во всех областях: рантайм, SDK,
🤩 Свежее превью .NET Microsoft выпустила первую предварительную версию .NET 11 с улучшениями во всех областях: рантайм, SDK, библиотеки, C#, ASP.NET Core, Blazor и .NET MAUI. ➡️ Библиотеки • Поддержка Zstandard compression для эффективного сжатия • BFloat16 — новый тип с плавающей точкой для ML-сценариев • Улучшения ZipArchiveEntry для работы с архивами • FrozenDictionary теперь поддерживает collection expressions ➡️ API и утилиты: • Расширенная поддержка Rune в String, StringBuilder и TextWriter • MediaTypeMap для определения MIME-типов • API верификации HMAC и KMAC • Создание жёстких ссылок • DivisionRounding для режимов целочисленного деления • Happy Eyeballs в Socket.ConnectAsync для быстрого подключения по IPv4/IPv6 ➡️ Рантайм • Runtime Async — улучшенная асинхронность на уровне рантайма • CoreCLR на WebAssembly — полноценный рантайм в браузере • Расширение интерпретатора • JIT-оптимизации производительности • GC Heap Hard Limit для 32-битных процессов • Поддержка архитектур RISC-V и s390x ➡️ SDKdotnet run теперь интерактивно выбирает целевой фреймворк и устройство • dotnet test поддерживает позиционные аргументы • dotnet watch — горячая перезагрузка для изменений в ссылках и настраиваемые порты ➡️ C# и F# • C#: передача коллекций как аргументов • C# расширенная поддержка раскладки памяти • F#: параллельная компиляция включена по умолчанию, ускорение компиляции вычислительных выражений, новые флаги --disableLanguageFeature и --typecheck-only для FSI. ➡️ Блог разработчиков 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #async_news

🧑‍💻 Закон Хайрама: почему вы не можете изменить свой API Формулировка закона: При достаточном количестве пользователей API
🧑‍💻 Закон Хайрама: почему вы не можете изменить свой API Формулировка закона:
При достаточном количестве пользователей API не имеет значения, что вы обещаете в контракте — все наблюдаемое поведение вашей системы станет чьей-то зависимостью.
Вы создали API. Написали документацию. Явно указали, что гарантируете, а что нет. Но пользователи будут полагаться не только на задокументированное поведение, но и на: • Порядок элементов в ответе • Формат временных меток • Текст сообщений об ошибках • Время отклика • Недокументированные эндпоинты • Побочные эффекты • Баги И любое изменение этого может сломать чей-то прод. Excel и ошибка 1900 года В ранних версиях Excel был баг: 1900 год считался високосным, но таковым не являлся. Пользователи создали сложные таблицы, которые зависели от этого неправильного вычисления. Microsoft не мог просто исправить баг — это сломало бы тысячи таблиц. Ошибка сохранялась до Excel 2003. Даже сейчас есть опция «Enable iterative calculation» для совместимости. 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #sharp_view

⭐️ SQL Server в одном файле LocalDB — это SQL Server в одном .mdf файле. Идеально для тестов, локальной разработки и инструментов. Создаётся одной командой, не требует установки сервера. LocalDB — это облегчённая версия SQL Server, которая: работает в режиме пользователя, то есть без сервиса, хранит базу в одном .mdf файле, ведёт себя как настоящий SQL Server и не требует установки полноценного SQL Server. Минимальный рабочий пример:
using Microsoft.Data.SqlClient;
using System.IO;

const string DatabaseName = "TestDatabase";
var databasePath = Path.Combine(
    Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
    "MyApp", "Data"
);

// Создаём директорию если её нет
if (!Directory.Exists(databasePath))
{
    Directory.CreateDirectory(databasePath);
}

var dataFile = Path.Combine(databasePath, $"{DatabaseName}.mdf");
var logFile = Path.Combine(databasePath, $"{DatabaseName}_log.ldf");

// Безопасное экранирование для SQL
var escapedDbName = DatabaseName.Replace("]", "]]");
var escapedDataPath = dataFile.Replace("'", "''");
var escapedLogPath = logFile.Replace("'", "''");

var masterConnection = new SqlConnectionStringBuilder
{
    DataSource = @"(localdb)\MSSQLLocalDB",
    InitialCatalog = "master",
    IntegratedSecurity = true,
    TrustServerCertificate = true
}.ConnectionString;

var createDbQuery = $"""
    IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = N'{escapedDbName}')
    BEGIN
        CREATE DATABASE [{escapedDbName}]
        ON PRIMARY (
            NAME = N'{escapedDbName}',
            FILENAME = N'{escapedDataPath}'
        )
        LOG ON (
            NAME = N'{escapedDbName}_log',
            FILENAME = N'{escapedLogPath}'
        )
        COLLATE Latin1_General_100_CI_AI_SC_UTF8;
    END
    """;

using var conn = new SqlConnection(masterConnection);
await conn.OpenAsync();

using var cmd = new SqlCommand(createDbQuery, conn);
await cmd.ExecuteNonQueryAsync();

Console.WriteLine($"База данных создана: {dataFile}");
Будут созданы необходимые файлы и база будет готова принимать подключения. Создание идемпотентное — повторный запуск безопасен. LocalDB работает под текущим пользователем Windows: • Папка должна быть доступна на запись • Не нужны права администратора • Файлы принадлежат пользователю Пакет: Microsoft.Data.SqlClient Требует: LocalDB. Он входит в Visual Studio или SQL Server Express. 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #sharp_view

👀 Смотрим видео про URL Работайте с API каждый день, но часто ли задумываетесь, как правильно строить эндпоинты. В видео под
👀 Смотрим видео про URL Работайте с API каждый день, но часто ли задумываетесь, как правильно строить эндпоинты. В видео подробно про пагинацию, query-параметры, фильтры, сортировки, поддомены, порты и пути с версионированием. ➡️ Подтянуть базу про URL 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #il_люминатор

👍 Модификатор protected internal В C# модификатор доступа protected internal открывает доступ к полю, методу или свойству из двух зон. Любые классы внутри той же сборки могут обращаться к такому члену напрямую. Наследники базового класса получают доступ, даже если они в другой сборке. Пример:
public class BaseClass
{
    protected internal int SecretValue = 42;
}
Protected internal оказывается самым широким среди комбинированных, кроме public. 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #sharp_view

🟥 Утечки данных в .NET-приложениях чаще происходят не из-за хакеров, а из-за неверной работы с ключами, конфигурациями и базовой криптографией. Ошибки на уровне кода быстро превращаются в инциденты. На открытом уроке разберём практическое применение System.Security.Cryptography: AES, RSA, хеширование и цифровые подписи. Поговорим о безопасном хранении и передаче секретов, управлении ключами и принципе наименьших привилегий. ❗️ Вы системно разберёте уязвимости OWASP Top-10 для .NET: инъекции, небезопасную десериализацию, XSS, CSRF — и способы их нейтрализации на уровне кода и архитектуры. Отдельно обсудим шифрование данных в БД, защиту строк подключения и безопасное логирование без утечек токенов. 🟥Встречаемся 10 февраля в 20:00 МСК в преддверии старта курса «C# Developer. Professional». Зарегистрируйтесь, чтобы не пропустить: https://clc.to/UzMt9g Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru