C# (C Sharp) programming
По всем вопросам- @notxxx1 Реестр РКН: https://clck.ru/3Fk3kb #VRHSZ
إظهار المزيد📈 نظرة تحليلية على قناة تيليجرام C# (C Sharp) programming
تُعد قناة C# (C Sharp) programming (@csharp_ci) في القطاع اللغوي الروسية لاعباً نشطاً. يضم المجتمع حالياً 18 126 مشتركاً، محتلاً المرتبة 7 044 في فئة التكنولوجيات والتطبيقات والمرتبة 36 287 في منطقة روسيا.
📊 مؤشرات الجمهور والحراك
منذ تأسيسه في невідомо، حقق المشروع نمواً سريعاً وجمع 18 126 مشتركاً.
بحسب آخر البيانات بتاريخ 30 أغسطس, 2026، تحافظ القناة على نشاط مستقر. خلال آخر 30 يوماً تغيّر عدد الأعضاء بمقدار -65، وفي آخر 24 ساعة بمقدار 0، مع بقاء الوصول العام مرتفعاً.
- حالة التحقق: غير موثّقة
- معدل التفاعل (ER): يبلغ متوسط تفاعل الجمهور 15.36%. وخلال أول 24 ساعة من النشر يحصد المحتوى عادةً 7.44% من ردود الفعل نسبةً إلى إجمالي المشتركين.
- وصول المنشورات: يحصل كل منشور على متوسط 2 784 مشاهدة. وخلال اليوم الأول يجمع عادةً 1 349 مشاهدة.
- التفاعلات والاستجابة: يتفاعل الجمهور بانتظام؛ متوسط التفاعلات لكل منشور يبلغ 0.
- الاهتمامات الموضوعية: يركز المحتوى على مواضيع رئيسية مثل .net, api, логика, архитектура, string.
📝 الوصف وسياسة المحتوى
يصف المؤلف القناة بأنها مساحة للتعبير عن الآراء الذاتية:
“По всем вопросам- @notxxx1
Реестр РКН: https://clck.ru/3Fk3kb
#VRHSZ”
بفضل وتيرة التحديث المرتفعة (أحدث البيانات بتاريخ 31 أغسطس, 2026) تحافظ القناة على حداثتها ومستوى وصول مرتفع. وتُظهر التحليلات تفاعلاً نشطاً من الجمهور، ما يجعلها نقطة تأثير مهمة ضمن فئة التكنولوجيات والتطبيقات.
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
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("1");
var task = FooAsync();
Console.WriteLine("2");
await task;
Console.WriteLine("5");
}
static async Task FooAsync()
{
Console.WriteLine("3");
await Task.Delay(100);
Console.WriteLine("4");
}
}
❓ Вопрос:
Какой порядок чисел появится в консоли?
👇 Подумай, прежде чем смотреть ответ.
—
✅ Разбор:
1. Console.WriteLine("1"); → печатает 1
2. var task = FooAsync(); → вызывается FooAsync(), который:
печатает 3
доходит до await Task.Delay(100); и возвращает управление в Main (не дожидаясь задержки)
3. Console.WriteLine("2"); → печатает 2
4. await task; → теперь Main ждёт завершения FooAsync
5. после 100ms продолжает выполнение в FooAsync → печатает 4
6. возвращаемся в Main → печатает 5
—
🎉 Окончательный вывод:
1
3
2
4
5
📝 Что проверяет задача:
- Понимание работы async/await
- Как работают точки приостановки (suspension points)
- Когда код возвращается в вызывающий метод
#CSharp #AsyncAwait #InterviewQuestion #CodeChallenge
@csharp_ci
$ErrorActionPreference = "Stop"
$rootFolder = Resolve-Path -Path "."
$oldName = "Sample.Foo"
$newName = "Sample.Bar"
# Rename files and folders
foreach ($item in Get-ChildItem -LiteralPath $rootFolder -Recurse | Sort-Object -Property FullName -Descending) {
$itemNewName = $item.Name.Replace($oldName, $newName)
if ($item.Name -ne $itemNewName) {
Rename-Item -LiteralPath $item.FullName -NewName $itemNewName
}
}
# Replace content in files
foreach ($item in Get-ChildItem -LiteralPath $rootFolder -Recurse -Include "*.cmd", "*.cs", "*.csproj", "*.json", "*.md", "*.proj", "*.props", "*.ps1", "*.sln", "*.slnx", "*.targets", "*.txt", "*.vb", "*.vbproj", "*.xaml", "*.xml", "*.xproj", "*.yml", "*.yaml") {
$content = Get-Content -LiteralPath $item.FullName
if ($content) {
$newContent = $content.Replace($oldName, $newName)
Set-Content -LiteralPath $item.FullName -Value $newContent
}
}
@csharp_ci