C# (C Sharp) programming
По всем вопросам- @notxxx1 Реестр РКН: https://clck.ru/3Fk3kb #VRHSZ
Mostrar más📈 Análisis del canal de Telegram C# (C Sharp) programming
El canal C# (C Sharp) programming (@csharp_ci) en el segmento lingüístico de Ruso es un actor destacado. Actualmente la comunidad reúne a 18 305 suscriptores, ocupando la posición 7 337 en la categoría Tecnologías y Aplicaciones y el puesto 36 917 en la región Rusia.
📊 Métricas de audiencia y dinámica
Desde su creación el невідомо, el proyecto ha mostrado un crecimiento acelerado, reuniendo a 18 305 suscriptores.
Según los últimos datos del 11 junio, 2026, el canal mantiene una actividad estable. En los últimos 30 días la variación de miembros fue de -27, y en las últimas 24 horas de 6, conservando un alto alcance.
- Estado de verificación: No verificado
- Tasa de interacción (ER): El promedio de interacción de la audiencia es 16.94%. Durante las primeras 24 horas tras publicar, el contenido suele obtener 8.35% de reacciones respecto al total de suscriptores.
- Alcance de las publicaciones: Cada publicación recibe en promedio 3 100 visualizaciones. En el primer día suele acumular 1 528 visualizaciones.
- Reacciones e interacción: La audiencia responde de forma activa: el promedio de reacciones por publicación es 0.
- Intereses temáticos: El contenido se centra en temas clave como .net, api, логика, архитектура, string.
📝 Descripción y política de contenido
El autor describe el recurso como un espacio para expresar opiniones subjetivas:
“По всем вопросам- @notxxx1
Реестр РКН: https://clck.ru/3Fk3kb
#VRHSZ”
Gracias a la alta frecuencia de actualizaciones (últimos datos recibidos el 12 junio, 2026), el canal mantiene la vigencia y un amplio alcance. La analítica demuestra que la audiencia interactúa activamente con el contenido, lo que lo convierte en un punto de referencia dentro de la categoría Tecnologías y Aplicaciones.
$ ls -a
А как смотрю я:
$ echo */ *. *
Этот трюк выводит всё “простым” способом через glob-расширение:
- */ покажет папки
- * покажет обычные файлы
- .* покажет скрытые файлы
Плюс это удобно тем, что результат можно сразу передавать дальше в команды, не парся вывод ls..csproj прямо сейчас.
Пакеты обычно выглядят так:
<PackageReference Include="Serilog" Version="4.3.0" />
<PackageReference Include="WolverineFx" Version="5.6.0" />
И в итоге проект превращается в мусорку из версий.
А теперь представь, что это будет так:
<PackageReference Include="Serilog" />
<PackageReference Include="WolverineFx" />
Вот в этом и кайф Central Package Management.
Что он даёт:
✅ .csproj становится чистым и читаемым
✅ никто случайно не поставит “левую” версию пакета
✅ вся команда работает на одинаковых версиях библиотек
✅ сборка становится предсказуемой и детерминированной
Как работает:
Ты управляешь версиями централизованно через файл
Directory.Packages.props в корне репозитория.
То есть версии пакетов задаются в одном месте, а проекты просто подключают зависимости без указания version.
Если у тебя монорепа или несколько проектов - это must-have.app.MapGet/MapPost превращается в ад.
Решение - авторегистрировать endpoints через DI.
Идея:
1) Делаешь общий интерфейс IEndpoint
2) Каждый endpoint реализует его
3) На старте приложения сканируешь сборку, регистрируешь все реализации в DI
4) Достаёшь их из DI и вызываешь MapEndpoints()
Плюсы:
✅ чистый Program.cs
✅ каждый endpoint в отдельном файле
✅ масштабируется без хаоса
✅ легко тестировать и поддерживать
Пример паттерна:
builder.Services.AddEndpoints(typeof(Program).Assembly);
public interface IEndpoint
{
void Map(IEndpointRouteBuilder app);
}
public static class EndpointExtensions
{
public static IServiceCollection AddEndpoints(this IServiceCollection services, Assembly assembly)
{
var endpoints = assembly.DefinedTypes
.Where(t => !t.IsAbstract && !t.IsInterface && typeof(IEndpoint).IsAssignableFrom(t))
.Select(t => ServiceDescriptor.Transient(typeof(IEndpoint), t))
.ToArray();
services.TryAddEnumerable(endpoints);
return services;
}
public static void MapEndpoints(this WebApplication app)
{
foreach (var endpoint in app.Services.GetServices<IEndpoint>())
endpoint.Map(app);
}
}appsettings.json в класс
- инжектишь настройки через DI
- приложение стартует без проблем ✅
А потом внезапно…
В прод падает , потому что:
❌ не задан обязательный ApiKey
❌ RetryCount = 0
❌ строка подключения пустая
И ты узнаёшь об этом только тогда, когда кто-то нажмёт нужную кнопку в твоем приложении.
Вот почему принцип Fail Fast критичен для конфигов:
если конфигурация невалидна - приложение не должно запускаться вообще.
Как это сделать правильно:
используй расширение Options Pattern через IValidateOptions.
Суть подхода:
1) задаём правила (например: ApiKey не null, `RetryCount > 0`)
2) регистрируем валидатор
3) если условия нарушены - DI кидает исключение сразу при старте ✅
Можно прйти дальше и подключиит FluentValidation, чтобы условия были:
- чище
- читабельнее
- удобнее расширять
Полная реализация: https://milanjovanovic.tech/blog/options-pattern-validation-in-aspnetcore-with-fluentvalidation?utm_source=X&utm_medium=social&utm_campaign=05.01.2026Microsoft.Extensions.Resilience
- Microsoft.Extensions.Http.Resilience
Они построены поверх Polly, поэтому API знакомый - легко описывать политики:
- retry
- circuit-breaker
- fallback
- timeout
- hedging
- rate limiter
Подключаете и ваши HTTP-клиенты и сервисы автоматически восстанавливаются при сетевых ошибках и таймаутах.
Итог: меньше падений и больше стабильности. Отлично для продакшена 🚀
using System;
class Base
{
public virtual void Foo(object o) => Console.WriteLine("Base.Foo(object)");
}
class Derived : Base
{
public override void Foo(object o) => Console.WriteLine("Derived.Foo(object)");
public void Foo(string s) => Console.WriteLine("Derived.Foo(string)");
}
class Program
{
static void Main()
{
Base b = new Derived();
b.Foo("A");
((Derived)b).Foo("A");
dynamic d = b;
d.Foo("A");
object x = "A";
d.Foo(x);
d.Foo(null);
}
}
📌 Ответ:
Derived.Foo(object)
Derived.Foo(string)
Derived.Foo(string)
Derived.Foo(string)
Derived.Foo(string)
Пояснение:
1) b.Foo("A")
Статический тип переменной - Base.
Компилятор видит только Foo(object).
Вызов виртуальный, поэтому выполняется override:
Derived.Foo(object)
2) ((Derived)b).Foo("A")
Статический тип - Derived.
Есть перегрузка Foo(string), она точнее для string:
Derived.Foo(string)
3) dynamic d = b; d.Foo("A")
dynamic откладывает выбор метода до runtime.
Реальный тип объекта - Derived.
Реальный тип аргумента - string:
Derived.Foo(string)
4) object x = "A"; d.Foo(x)
Для dynamic учитывается реальный тип аргумента.
x содержит string:
Derived.Foo(string)
5) d.Foo(null)
null подходит и для object, и для string.
string - более специфичный тип:
Derived.Foo(string)
¡Ya disponible! Investigación de Telegram 2025 — los principales insights del año 
