C# (C Sharp) programming
По всем вопросам- @notxxx1 Реестр РКН: https://clck.ru/3Fk3kb #VRHSZ
نمایش بیشتر📈 تحلیل کانال تلگرام C# (C Sharp) programming
کانال C# (C Sharp) programming (@csharp_ci) در بخش زبانی روسی بازیگری فعال است. در حال حاضر جامعه شامل 18 129 مشترک است و جایگاه 7 042 را در دسته فناوری و برنامهها و رتبه 36 294 را در منطقه روسيا دارد.
📊 شاخصهای مخاطب و پویایی
از زمان ایجاد در невідомо، پروژه رشد سریعی داشته و 18 129 مشترک جذب کرده است.
بر اساس آخرین دادهها در تاریخ 28 اوت, 2026، کانال فعالیت پایداری دارد. در ۳۰ روز گذشته تغییر اعضا برابر -66 و در ۲۴ ساعت گذشته برابر -1 بوده و همچنان دسترسی گستردهای حفظ شده است.
- وضعیت تأیید: تأیید نشده
- نرخ تعامل (ER): میانگین تعامل مخاطب 15.26% است و در ۲۴ ساعت نخست پس از انتشار، محتوا معمولاً 7.43% واکنش نسبت به کل مشترکان کسب میکند.
- دسترسی پستها: هر پست به طور میانگین 2 767 بازدید دریافت میکند. در اولین روز معمولاً 1 348 بازدید جمعآوری میشود.
- واکنشها و تعامل: مخاطبان بهطور فعال حمایت میکنند؛ میانگین واکنش به هر پست 0 است.
- علایق موضوعی: محتوا بر موضوعات کلیدی مانند .net, api, логика, архитектура, string تمرکز دارد.
📝 توضیح و سیاست محتوایی
نویسنده این فضا را محل بیان دیدگاههای شخصی توصیف میکند:
“По всем вопросам- @notxxx1
Реестр РКН: https://clck.ru/3Fk3kb
#VRHSZ”
به لطف بهروزرسانیهای پرتکرار (آخرین داده در تاریخ 29 اوت, 2026)، کانال همواره بهروز و دارای دسترسی بالاست. تحلیلها نشان میدهد مخاطبان بهطور فعال با محتوا تعامل دارند و آن را به نقطه اثرگذاری مهم در دسته فناوری و برنامهها تبدیل کردهاند.
date DESC, id DESC, лимит на 1000 записей и composite index по (date, id). На первый взгляд, все должно работать быстро.
Но EXPLAIN ANALYZE показывает другое: Postgres вроде бы использует Index Scan, но после этого выкидывает 900 000 строк через Filter.
То есть индекс есть, но запрос все равно тащит слишком много лишнего.
Проблема в условии:
`date < @date OR (date = @date AND id <= @lastId)`
Для разработчика это выглядит логично: сначала сравниваем дату, потом id.
Но для оптимизатора такой OR плохо ложится на composite index. В итоге база не может сразу пойти по нужному диапазону и вынуждена фильтровать огромный кусок данных.
Правильнее записать условие через tuple comparison:
`(date, id) <= (@date, @lastId)`
Смысл тот же, но для Postgres это уже понятный диапазон по составному индексу.
И результат: 298 мс превращаются в 0,66 мс.
Индекс сам по себе ничего не гарантирует.
Важно не только создать индекс, но и написать запрос так, чтобы оптимизатор реально смог его использовать.Guid.NewGuid().
Проблема в том, что классический UUID случайный. Для уникальности это удобно, но для базы данных - не всегда.
Когда значения генерируются хаотично, новые записи вставляются в разные части индекса. Отсюда:
- больше фрагментации
- дороже вставки
- чаще перестраиваются страницы индекса
- хуже поведение на больших таблицах
Поэтому многие разработчики начали использовать ULID.
ULID состоит из двух частей:
- timestamp
- random
За счет timestamp такие ID сортируются по времени, а значит база может вставлять новые записи более последовательно.
Но начиная с .NET 9 появился встроенный вариант:
Guid.CreateVersion7()
UUID v7 тоже содержит временную часть, поэтому лучше подходит для индексируемых ключей, чем полностью случайный UUID.
Главное отличие:
ULID - отдельный формат и часто сторонняя библиотека.
UUID v7 - обычный Guid, который уже поддерживается в .NET.
Для новых проектов это выглядит как более разумный дефолт:
- не Guid.NewGuid()
- не отдельный ULID-пакет
- а Guid.CreateVersion7()
Особенно если Guid используется как primary key в базе. async Task<IActionResult> пишется на автомате. Вы точно знаете, почему EF Core сгенерировал именно такой SQL - и как переписать запрос, чтобы он летал.
Это не фантазия. Это результат после 16 модулей, в которых каждая концепция объясняется через код и закрепляется практикой.
ООП, SOLID, LINQ, async/await, DI, EF Core, ASP.NET Core, Docker, Kubernetes - всё, что казалось магией, станет рабочим инструментом.
А бонусом - портфолио проектов: от CLI-утилит и REST API до собственного SaaS с multi-tenancy, JWT и деплоем в Kubernetes под TLS.
Скидка - 58% доступна 48 часов: https://stepik.org/a/282984/fingerd`, переполнял буфер и заставлял систему выполнять чужой код.
Итог: около 6000 машин были заражены за считанные часы. По оценкам того времени, это была примерно десятая часть всего интернета.
Самое безумное здесь не сам червь, а то, насколько маленькой была причина. Один небезопасный вызов. Один буфер без проверки. Одна функция, которую годами использовали как обычный инструмент.
Позже `gets()` признали настолько опасной, что её фактически выкинули из современного C.
Урок простой: в системном программировании безопасность часто ломается не на сложной криптографии, а на банальном «а что будет, если ввод окажется длиннее, чем мы ожидали?»
#history[InlineData(...)], когда параметры можно прямо указать над тестом.
Если данных больше или нужна нормальная типизация, можно вынести их в TheoryData<T> и подключить через [ClassData(typeof(...))].
Смысл простой: меньше копипасты, чище тесты, проще добавлять новые кейсы.
Вместо пяти почти одинаковых тестов - один понятный сценарий и набор входных данных.
Для xUnit это один из тех приемов, который быстро окупается в любом C# проекте.ApiVersionSet: можно явно объявить поддерживаемые версии, включить репортинг доступных версий и привязать конкретный endpoint к нужной версии.
В примере создается набор версий API:
v1 - текущая стабильная версия
v2 - новая версия для развития контракта
После этого endpoint /api/v{version:apiVersion}/workouts/{workoutId} получает привязку через .WithApiVersionSet(apiVersionSet) и явно мапится на .MapToApiVersion(1).
Главная идея простая: версия становится частью маршрута, а не скрытой договоренностью между клиентом и backend.
Это особенно важно, когда API уже используют мобильные приложения, внешние интеграции или несколько фронтендов. Вы можете развивать v2, не ломая клиентов, которые все еще сидят на v1.
Для C# backend-разработчика это один из тех паттернов, который выглядит мелочью на старте, но сильно экономит нервы на проде.
public decimal CalculateTotal(Order order)
{
decimal total = 0;
if (order != null)
{
if (order.Items != null)
{
foreach (var item in order.Items)
{
if (item != null)
{
if (item.IsActive)
{
if (item.Price > 0)
{
if (item.Quantity > 0)
{
total += item.Price * item.Quantity;
}
}
}
}
}
}
if (order.Customer != null)
{
if (order.Customer.IsVip)
{
total = total * 0.9m;
}
}
}
return total;
}
Как бы ты почистил этот код?
A - Заменить вложенные if на guard clauses
B - Использовать LINQ для фильтрации и суммы
C - Вынести скидку VIP в отдельный метод
D - Все варианты выше
@csharp_ci async Task<IActionResult> пишется на автомате. Вы точно знаете, почему EF Core сгенерировал именно такой SQL - и как переписать запрос, чтобы он летал.
Это не фантазия. Это результат после 16 модулей, в которых каждая концепция объясняется через код и закрепляется практикой.
ООП, SOLID, LINQ, async/await, DI, EF Core, ASP.NET Core, Docker, Kubernetes - всё, что казалось магией, станет рабочим инструментом.
А бонусом - портфолио проектов: от CLI-утилит и REST API до собственного SaaS с multi-tenancy, JWT и деплоем в Kubernetes под TLS.
Скидка - 58% доступна 48 часов: https://stepik.org/a/282984/
foreach (var transaction in GetTransactions(userId))
{
// boom, если null
}
В итоге получаешь:
• лишние null-проверки повсюду
• более громоздкий код
• ошибки в рантайме, если кто-то забыл проверить
Всегда этого возвращай пустую коллекцию:
Enumerable.Empty<T>()
new List<T>()
[] в C# 12
var transactions = GetTransactions(userId)
?? Enumerable.Empty<TransactionDto>();
Теперь код становится чище и понятнее.
Ты всегда можешь итерироваться и не думаешь о null каждый раз.
Хороший API - это тот, в работе с которым ошибиться почти невозможно.