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 030 suscriptores, ocupando la posición 7 242 en la categoría Tecnologías y Aplicaciones y el puesto 36 510 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 030 suscriptores.
Según los últimos datos del 29 octubre, 2026, el canal mantiene una actividad estable. En los últimos 30 días la variación de miembros fue de -54, y en las últimas 24 horas de -9, conservando un alto alcance.
- Estado de verificación: No verificado
- Tasa de interacción (ER): El promedio de interacción de la audiencia es 15.19%. Durante las primeras 24 horas tras publicar, el contenido suele obtener 8.07% de reacciones respecto al total de suscriptores.
- Alcance de las publicaciones: Cada publicación recibe en promedio 2 738 visualizaciones. En el primer día suele acumular 1 455 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 30 octubre, 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.
var result = await AC<LegacyUserDTO, NewUserModel>(legacyUser);
— преобразует старую DTO-модель в новую без ручной работы
var request = new MathRequest { Tokens = new() { "(", "2", "+", "3", ")", "*", "4", "-", "6", "/", "3" } };
var response = await AC<MathRequest, MathResponse>(request);
— рассчитывает результат выражения и генерирует пошаговое решение
⚠️ Проект предназначен только для демонстрации — в продакшн пока не стоит запускать, но как proof-of-concept это отличная иллюстрация, как LLM могут расширять возможности .NET-разработки.
🔗 Репозиторийstruct с интерфейсами. Поведение кажется очевидным — но только на первый взгляд.
📦 Задача
using System;
public interface ICounter
{
void Increment();
int Value { get; }
}
public struct Counter : ICounter
{
private int _value;
public void Increment()
{
_value++;
}
public int Value => _value;
}
class Program
{
static void Main()
{
ICounter counter = new Counter();
counter.Increment();
counter.Increment();
Console.WriteLine(counter.Value);
}
}
❓ Что выведет код?
A) 0
😎 1
C) 2
D) Ошибка компиляции
💡 Разбор
Наивный ответ — 2, ведь Increment() вызывается дважды. Но!
📦 Counter — это struct, то есть value type.
Когда мы присваиваем Counter переменной типа ICounter, происходит boxing — создаётся копия структуры в heap.
🔁 Каждый вызов counter.Increment() работает с новой копией, потому что интерфейс не может напрямую изменить struct без создания временного объекта.
🧱 В итоге Increment() изменяет внутреннее состояние временной копии, но не оригинального значения.
✅ Ответ: 0
🧨 Подвох
Использование struct через интерфейс приводит к boxing.
Вызываемые методы действуют на копии, а не на оригинале.
Изменения теряются, и это не ошибка компиляции — это логическая ловушка.
🔧 Как исправить?
Вариант 1: Сделать Counter классом:
```csharp
public class Counter : ICounter
{
private int _value;
public void Increment() => _value++;
public int Value => _value;
}
public class Counter : ICounter
{
private int _value;
public void Increment() => _value++;
public int Value => _value;
}```
@csharp_ci
using System;
using System.Threading;
class Program
{
static Lazy<HeavyObject> _heavy = new Lazy<HeavyObject>(() =>
{
Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}] Initializing HeavyObject...");
return new HeavyObject();
});
static void Main()
{
for (int i = 0; i < 5; i++)
{
new Thread(() =>
{
Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}] Accessing HeavyObject...");
var obj = _heavy.Value;
}).Start();
}
Console.ReadLine();
}
}
class HeavyObject
{
public HeavyObject()
{
Thread.Sleep(1000); // эмуляция долгой инициализации
Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}] HeavyObject created.");
}
}
❓ Вопрос:
Сколько раз вы увидите сообщение Initializing HeavyObject... и HeavyObject created.? Почему это может удивить даже опытных .NET разработчиков?
🔍 Разбор:
На первый взгляд вы ожидаете, что:
- `Lazy<T>` гарантирует **ленивую инициализацию один раз** даже при многопоточном доступе.
- Сообщение `Initializing HeavyObject...` и конструктор `HeavyObject` сработают только один раз.
Но! Тут есть подвох.
По умолчанию `Lazy<T>` использует **LazyThreadSafetyMode.ExecutionAndPublication**. Это гарантирует, что даже если несколько потоков обращаются к `.Value` одновременно, объект будет инициализирован **только один раз**.
✅ **Ожидаемый вывод:**
- Каждый поток пишет `Accessing HeavyObject...`
- Только один поток пишет `Initializing HeavyObject...` и `HeavyObject created.`
- Остальные потоки дождутся завершения и получат уже готовый объект.
Примерный вывод:
```
[4] Accessing HeavyObject...
[5] Accessing HeavyObject...
[6] Accessing HeavyObject...
[7] Accessing HeavyObject...
[8] Accessing HeavyObject...
[4] Initializing HeavyObject...
[4] HeavyObject created.
```
🌀 **Подвох, если сменить режим:**
Если вы немного измените код вот так:
```csharp
static Lazy<HeavyObject> _heavy = new Lazy<HeavyObject>(
() =>
{
Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}] Initializing HeavyObject...");
return new HeavyObject();
},
LazyThreadSafetyMode.None // без потокобезопасности
);
```
То при **одновременном** доступе к `.Value` вы получите **несколько инициализаций** (по сути гонку потоков).
Примерный вывод может быть таким:
```
[4] Accessing HeavyObject...
[5] Accessing HeavyObject...
[6] Accessing HeavyObject...
[4] Initializing HeavyObject...
[5] Initializing HeavyObject...
[6] Initializing HeavyObject...
[4] HeavyObject created.
[5] HeavyObject created.
[6] HeavyObject created.
```
Итого объект будет создан несколько раз, что ломает инварианты "Lazy должен создавать объект один раз".
✅ **Вывод:**
• По умолчанию `Lazy<T>` **потокобезопасен**, но важно понимать, что это можно **изменить**.
• При работе с многопоточностью в .NET всегда обращайте внимание на **режим LazyThreadSafetyMode**.
• Даже опытные разработчики могут не заметить подвоха, если кто-то по ошибке или из оптимизаций использует `LazyThreadSafetyMode.None`.
💡 **Бонус-вопрос:**
Что произойдёт, если ваш factory-метод (лямбда) выбросит исключение при инициализации? Как `Lazy<T>` поведёт себя при следующем доступе к .Value?
@csharp_ci