C# | Вопросы собесов
5.1K subscribers
35 photos
1 video
1 file
994 links
Download Telegram
🤔 Что такое Abstract class?

Абстрактный класс — это класс, от которого нельзя создать объект напрямую.
Он может содержать:
- абстрактные методы (без реализации),
- обычные методы (с реализацией).
Используется для создания базовой функциональности, которую дополняют наследники.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🤔 Можно ли передать значимый тип данных по ссылке?

Да, можно!
По умолчанию значимые типы (структуры, int, double) передаются по значению.
Но их можно передать по ссылке с помощью ref или out.

🚩Передача по значению (обычное поведение)

Копия передаётся в метод, а оригинал не меняется.
void ChangeValue(int number)
{
number = 10; // Изменится только копия
}

int x = 5;
ChangeValue(x);
Console.WriteLine(x); // 5 (значение не изменилось)


🚩Передача значимого типа по ссылке (`ref`)

Позволяет менять оригинальную переменную.
void ChangeValue(ref int number)
{
number = 10; // Меняем оригинальное значение
}

int x = 5;
ChangeValue(ref x);
Console.WriteLine(x); // 10 (значение изменилось)


🚩Использование `out` (без начального значения)

out тоже передаёт по ссылке, но требует обязательного присвоения внутри метода.
void InitializeValue(out int number)
{
number = 100; // Обязательно присваиваем значение
}

int x;
InitializeValue(out x);
Console.WriteLine(x); // 100


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🤔1
🤔 Что такое абстракция?

Абстракция — это принцип ООП, который выделяет только важные характеристики объекта, скрывая сложные детали его реализации. Это помогает упростить взаимодействие с объектами и сконцентрироваться на их использовании, а не на внутренней структуре.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🤔 Зачем сделали ref & out для ссылочных типов?

В C# ключевые слова ref и out используются для передачи аргументов по ссылке, что позволяет методам изменять значения этих аргументов. Эти механизмы полезны как для значимых типов (структур), так и для ссылочных типов (объектов). Давайте рассмотрим более детально, зачем и как их используют для ссылочных типов.

🚩`ref`

С помощью ref можно передавать ссылочные типы таким образом, чтобы метод мог изменять саму ссылку, то есть ссылаться на другой объект.

🚩`out`

Ключевое слово out позволяет передавать аргумент, который не обязательно должен быть инициализирован до вызова метода. Метод, принимающий out аргумент, обязан присвоить ему значение до завершения работы.

🚩Как используются `ref` и `out`?

Пример использования ref
class Program
{
static void ChangeReference(ref MyClass obj)
{
obj = new MyClass { Value = 20 };
}

static void Main()
{
MyClass myObj = new MyClass { Value = 10 };
ChangeReference(ref myObj);
Console.WriteLine(myObj.Value); // Output: 20
}
}

class MyClass
{
public int Value { get; set; }
}


Пример использования out
class Program
{
static void InitializeObject(out MyClass obj)
{
obj = new MyClass { Value = 30 };
}

static void Main()
{
MyClass myObj;
InitializeObject(out myObj);
Console.WriteLine(myObj.Value); // Output: 30
}
}

class MyClass
{
public int Value { get; set; }
}


🚩Почему это нужно?

🟠Гибкость
ref и out добавляют гибкости при работе с методами, позволяя им изменять ссылки на объекты или создавать и возвращать новые объекты.

🟠Оптимизация
Эти механизмы могут быть полезны для оптимизации, когда необходимо избежать лишнего копирования данных, особенно при работе с большими объектами.

🟠Логика инициализации
out полезен для методов, которые должны вернуть несколько значений или инициализировать объекты, которые не могут быть инициализированы заранее.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🤔 Что такое лямбда выражения в С#?

Лямбда-выражения — это анонимные функции, которые используются для создания кратких методов или делегатов в C#. Они упрощают работу с LINQ, коллекциями и обратными вызовами. Лямбда-выражения могут захватывать переменные из своей области видимости, делая их удобным способом для создания замыканий. Используются для упрощения и улучшения читаемости кода.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊1
🤔 Каковы преимущества и недостатки использования контейнеров, таких как Docker в .NET приожениях?

Использование контейнеров, таких как Docker, в .NET приложениях имеет множество преимуществ, но также и некоторые недостатки. Вот основные из них:

🚩Плюсы

Портативность
Контейнеры включают все необходимые зависимости и настройки, что позволяет легко переносить приложения между различными средами (разработка, тестирование, производство) без изменения кода.
Пример: Docker-образ, созданный на локальной машине разработчика, может быть запущен на сервере производства без изменений.

Изолированность
Контейнеры изолируют приложения и их зависимости, предотвращая конфликты между различными версиями библиотек и инструментов.
Пример: Разные версии .NET Core могут сосуществовать на одной машине в разных контейнерах.

Легкость масштабирования
Контейнеры легко масштабировать горизонтально, создавая новые экземпляры приложения в ответ на увеличивающуюся нагрузку.
Пример: В Kubernetes можно легко добавить новые поды с контейнерами, чтобы справиться с повышенной нагрузкой.

Быстрое развертывание и запуск
Контейнеры запускаются быстрее, чем виртуальные машины, так как они не требуют загрузки всей операционной системы.
Пример: Docker-контейнер может быть запущен за несколько секунд, тогда как виртуальная машина может загружаться несколько минут.

Консистентность среды
Контейнеры обеспечивают консистентность среды между разработкой, тестированием и продакшн-окружением.
Пример: Одинаковая версия .NET Runtime и конфигурации могут быть гарантированы во всех средах.

Упрощенная CI/CD
Контейнеры интегрируются с инструментами CI/CD, что упрощает автоматизацию сборки, тестирования и развертывания.
Пример: Jenkins или GitHub Actions могут использовать Docker для создания и тестирования приложений в изолированных средах.

🚩Минусы

Изучение и сложность
Понимание и настройка контейнеров и связанных инструментов требует времени и навыков.
Пример: Изучение Docker, Docker Compose и Kubernetes может занять значительное время для команды.

Производительность
Хотя контейнеры легче, чем виртуальные машины, они все равно добавляют некоторую накладную на производительность.
Пример: Контейнеры могут использовать больше ресурсов, чем напрямую запущенные на хосте процессы, особенно при интенсивных I/O операциях.

Безопасность
Контейнеры изолируют процессы, но изоляция не так сильна, как у виртуальных машин. Ошибки конфигурации могут привести к проблемам безопасности.
Пример: Уязвимость в Docker или неправильная конфигурация сетевых правил могут привести к компрометации контейнера.

Ограничения хост-системы
Контейнеры зависят от хост-операционной системы и её ядра. Это может вызвать проблемы совместимости.
Пример: Windows-контейнеры не могут быть запущены на Linux-системах и наоборот.

Управление состоянием и данными
Контейнеры лучше всего подходят для безгосударственных приложений. Управление состоянием и данными может быть сложным.
Пример: Работа с постоянными данными требует настройки volume'ов или использование внешних систем хранения данных.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2💊1
🤔 Сравнение паттернов Adapter и Decorator

1. Adapter: преобразует интерфейс одного класса в интерфейс, который ожидает клиент; используется для интеграции несовместимых компонентов.
2. Decorator: добавляет новую функциональность существующему объекту без изменения его структуры.
3. Adapter изменяет совместимость, а Decorator — поведение объекта.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥1
🤔 Что такое сборщик мусора?

Сборщик мусора (Garbage Collector, GC) — это форма автоматического управления памятью. Он отслеживает каждый объект, выделенный в куче, и определяет, какие объекты более не доступны для приложения, а затем освобождает память, занимаемую этими объектами. Это ключевой компонент во многих современных языках программирования и средах выполнения, облегчая задачу управления памятью.

🚩Основные этапы работы

🟠Маркировка (Marking)
Сборщик мусора периодически проходит через все объекты в куче, начиная с "корней" (объектов, непосредственно доступных в программе, например, через переменные в стеке вызовов и глобальные переменные). Он отмечает все объекты, до которых можно добраться напрямую или косвенно.

🟠Очистка (Sweeping)
После маркировки доступных объектов, сборщик мусора удаляет все непомеченные объекты, освобождая ресурсы, которые они занимали.

🟠Компактификация (Compacting)
Некоторые сборщики мусора перемещают оставшиеся объекты, чтобы уменьшить фрагментацию памяти и улучшить производительность работы с памятью.

🚩Ограничения

🟠Производительность
Процесс сборки мусора может быть ресурсоёмким и может привести к заметным паузам в выполнении программы, особенно если куча большая.
🟠Непредсказуемость
Точное время сборки мусора может быть непредсказуемым, что может создавать проблемы в приложениях с реальным временем.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Какие есть подходы в рамках EF Core?

Entity Framework Core предлагает несколько стратегий работы с зависимостями и контекстом:
- Scoped контекст — создаётся на время одного запроса.
- Transient контекст — создаётся каждый раз заново.
- Singleton — крайне редко используется, так как контекст не потокобезопасен.
Также в EF Core есть несколько подходов к маппингу и конфигурации:
- Fluent API (в OnModelCreating)
- Аннотации атрибутов ([Key], [Required] и др.)
- Разделение конфигураций на отдельные классы (EntityTypeConfiguration)


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔8🔥2💊1
🤔 Что такое interceptor?

Interceptor (перехватчик) — это паттерн программирования, используемый для перехвата и обработки вызовов методов, запросов или событий перед их исполнением или после. В контексте C# и .NET, интерцепторы чаще всего применяются в:
ASP.NET Core Middleware — для перехвата HTTP-запросов.
Entity Framework Core Interceptors — для перехвата SQL-запросов и изменений данных.
Aspect-Oriented Programming (AOP) — для добавления кода перед или после выполнения метода.

🚩Зачем нужен Interceptor?

🟠Логирование
можно записывать запросы, исключения, время выполнения.
🟠Безопасность
проверка прав доступа перед выполнением запроса.
🟠Транзакции
автоматическое управление транзакциями в базе данных.
🟠Изменение поведения методов
например, автоматическая подмена аргументов.
🟠Кэширование
можно сохранять результаты выполнения метода.

🚩Пример использования Interceptor в Entity Framework Core

Entity Framework Core позволяет использовать интерцепторы для перехвата SQL-запросов. Это может быть полезно, например, для логирования всех SQL-запросов.
using Microsoft.EntityFrameworkCore.Diagnostics;
using System;
using System.Data.Common;
using System.Threading;
using System.Threading.Tasks;

public class SqlInterceptor : DbCommandInterceptor
{
public override InterceptionResult<DbDataReader> ReaderExecuting(
DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result)
{
Console.WriteLine($"SQL Query: {command.CommandText}");
return base.ReaderExecuting(command, eventData, result);
}
}


Теперь подключим этот интерцептор в DbContext
using Microsoft.EntityFrameworkCore;

public class MyDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.AddInterceptors(new SqlInterceptor());
base.OnConfiguring(optionsBuilder);
}
}


🚩Пример использования Interceptor в ASP.NET Core (Middleware)

В ASP.NET Core интерцепторы можно реализовать через Middleware. Например, перехватим все HTTP-запросы и добавим в лог
public class RequestInterceptor
{
private readonly RequestDelegate _next;

public RequestInterceptor(RequestDelegate next)
{
_next = next;
}

public async Task Invoke(HttpContext context)
{
Console.WriteLine($"HTTP Request: {context.Request.iss.onethod} {context.Request.Path}");
await _next(context);
}
}


Добавляем middleware в Program.cs
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.UseMiddleware<RequestInterceptor>();

app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});

app.Run();


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Как выглядит using после компиляции?

Конструкция using преобразуется в try-finally, чтобы гарантировать вызов Dispose().


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6👍2
🤔 Какие есть методы запросов жизненного цикла в asp.net Core?

В ASP.NET Core жизненный цикл запроса проходит несколько этапов — от получения HTTP-запроса до отправки ответа. В этом процессе участвуют Middleware, контроллеры, фильтры и обработчики событий.

🚩Основные этапы жизненного цикла запроса

Получение запроса (HttpContext создаётся)
Обработка через Middleware (передача запроса вниз)
Маршрутизация (Routing) — определение контроллера
Фильтры (например, аутентификация)
Вызов контроллера и метода (Action)
Обратный проход через Middleware (формирование ответа)
Отправка ответа клиенту

🚩Методы Middleware (Промежуточное ПО)

Middleware — это основной механизм обработки запросов.
Где регистрируются? → В Program.csapp.Use...)
Методы Middleware
app.Use(async (context, next) =>
{
Console.WriteLine("Перед обработкой запроса");
await next(); // Передаём запрос дальше
Console.WriteLine("После обработки запроса");
});


🚩Методы в контроллерах (`Controller`)

Контроллер обрабатывает запросы после маршрутизации.
Основные методы
public class HomeController : Controller
{
// Метод вызывается при GET-запросе
public IActionResult Index()
{
return View();
}

// Метод вызывается при POST-запросе
[HttpPost]
public IActionResult SubmitForm(FormModel model)
{
return RedirectToAction("Index");
}
}


🚩Фильтры (`Filters`)
Фильтры выполняются до и после вызова контроллера.
Методы фильтров
public class MyActionFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
Console.WriteLine("Перед вызовом метода контроллера");
}

public void OnActionExecuted(ActionExecutedContext context)
{
Console.WriteLine("После вызова метода контроллера");
}
}


🚩Методы жизненного цикла в `Program.cs`

В ASP.NET Core 6+ вся конфигурация находится в Program.cs.
Методы инициализации
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews(); // Подключаем MVC

var app = builder.Build();

app.UseRouting(); // Включаем маршрутизацию
app.UseAuthorization(); // Проверка прав
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers(); // Подключаем контроллеры
});

app.Run();


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Как работают join?

join в LINQ или SQL объединяет данные из двух коллекций или таблиц на основе общего поля. Например, в SQL это выполняется через сравнение ключей, указанных в ON, а в LINQ — с помощью метода Join. Результат может быть внутренним (INNER JOIN), внешним (LEFT JOIN, RIGHT JOIN) или полным (FULL JOIN).


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Когда можно использовать using?

Ключевое слово using используется в двух основных контекстах: для управления областью видимости объектов, реализующих интерфейс IDisposable, и для включения пространств имён.

🟠Управление областью видимости объектов (IDisposable)
Можно использовать для создания блока кода, внутри которого объекты, реализующие интерфейс IDisposable, автоматически освобождаются по завершении блока. Это удобно для управления ресурсами, такими как файловые потоки, базы данных или другие ресурсы системы, которые требуют явного освобождения.
using (StreamWriter writer = new StreamWriter("example.txt"))
{
writer.WriteLine("Hello, world!");
}
// Здесь объект writer уже автоматически закрыт и освобожден.


🟠Включение пространств имён
Также используется для объявления пространств имен, которые будут использоваться в коде, позволяя обращаться к классам внутри этих пространств без полного указания их имён.
using System;
using System.IO;
using System.Text;

// Теперь можно использовать классы из System, System.IO и System.Text без полного указания имени.


🟠using для статических классов (C# 6.0 и выше)
Для включения статических классов, что позволяет обращаться к статическим членам класса напрямую без указания имени класса.
using static System.Console;
using static System.Math;

class Program
{
static void Main()
{
WriteLine(Sqrt(144)); // Использование метода WriteLine и Sqrt без указания классов Console и Math
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Что под собой подразумевает mutex?

Mutex (мьютекс) — это механизм исключительного доступа. Он позволяет только одному потоку или процессу использовать ресурс в конкретный момент. Остальные ждут, пока мьютекс не освободится. Это полезно при межпоточном или межпроцессном взаимодействии.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Что такое паттерн MVVM?

MVVM (Model-View-ViewModel) — это паттерн проектирования, который разделяет логику программы и интерфейс пользователя. Он широко используется в WPF, Xamarin, MAUI и Blazor.

🚩Как они взаимодействуют?

ViewModel обновляет Model (через Command и INotifyPropertyChanged).
Model уведомляет ViewModel об изменениях.
View автоматически обновляется (через Data Binding).

🚩Пример MVVM в WPF

Model (Модель)
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}


ViewModel (Логика)
using System.ComponentModel;
using System.Runtime.CompilerServices;

public class PersonViewModel : INotifyPropertyChanged
{
private string _name;
public string Name
{
get => _name;
set { _name = value; OnPropertyChanged(); }
}

public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}


View (XAML)
<TextBox Text="{Binding Name, Mode=TwoWay}" />
<TextBlock Text="{Binding Name}" />


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3👍1
🤔 Какие шаблоны проектирования используешь во front- и back-end?

Front-end:
- MVVM (Model-View-ViewModel) — используется во фреймворках вроде WPF, Angular.
- MVC (Model-View-Controller) — в JavaScript-приложениях (например, с Backbone).
- Observer — реактивные библиотеки (RxJS).
- Strategy — динамическое поведение компонентов.
- Factory — динамическое создание UI-компонентов.
Back-end (на .NET):
- Repository — изолирует работу с базой данных.
- Unit of Work — объединяет операции изменения данных в одну транзакцию.
- Dependency Injection — внедрение зависимостей (широко используется в
ASP.NET Core).
- Factory Method — для создания объектов с гибкой конфигурацией.
- Adapter/Decorator — обёртки над внешними API или логикой.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔1
🤔 Какой сейчас последний C#?

🚩Нововведения

🟠Primary Constructors для классов и структур
Позволяют определять конструкторы прямо в объявлении класса или структуры, что упрощает код и улучшает его читаемость.
public class Person(string name, int age)
{
public string Name { get; } = name;
public int Age { get; } = age;
}


🟠Collection Literals
Обеспечивает более удобный синтаксис для создания коллекций.
var numbers = [1, 2, 3, 4, 5];


🟠Default Values для auto-properties
Теперь можно задавать значения по умолчанию для auto-properties, что делает код более лаконичным.
public string Name { get; set; } = "Unknown";


🟠Using aliases
Позволяет использовать алиасы для пространств имен, улучшая читаемость кода.
using Text = System.Text;


🟠Improved Lambda Expressions:
Улучшены возможности для работы с лямбда-выражениями, делая их более гибкими и мощными.

🚩Зачем нужны эти изменения?

Эти нововведения направлены на упрощение синтаксиса языка, улучшение читаемости и поддерживаемости кода, а также на повышение производительности и удобства разработки.
public class Program
{
public static void Main()
{
var person = new Person("John", 30);
Console.WriteLine($"Name: {person.Name}, Age: {person.Age}");

var numbers = [1, 2, 3, 4, 5];
numbers.ForEach(n => Console.WriteLine(n));

var name = new Name { Value = "Unknown" };
Console.WriteLine(name.Value);
}
}

public class Person(string name, int age)
{
public string Name { get; } = name;
public int Age { get; } = age;
}

public class Name
{
public string Value { get; set; } = "Default Name";
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Два подхода проектирования баз данных и кода

1. Code First:
- Сначала пишется модель в коде (Entity, классы).
- Потом генерируется схема БД.
- Гибкий, удобен для разработчиков.
2. Database First:
- Сначала создаётся база данных, таблицы, связи.
- Генерируются классы по схеме.
- Используется, когда БД уже существует или управляется отдельно.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
🤔 Что такое Dispose?

Dispose метод является частью паттерна управления ресурсами, известного как "Dispose Pattern". Этот метод реализуется в классах через интерфейс IDisposable. Цель — явное освобождение неуправляемых ресурсов и, по желанию, управляемых ресурсов, прежде чем сборщик мусора освободит объект. Это важно для эффективного управления памятью и другими системными ресурсами.

🚩Неуправляемые и управляемые ресурсы

🟠Неуправляемые ресурсы
включают в себя ресурсы, которые не управляются средой CLR (Common Language Runtime), например, файловые дескрипторы, сетевые соединения или указатели на память, выделенную вне .NET среды.
🟠Управляемые ресурсы
это объекты .NET, которые занимают память и потенциально удерживают ссылки на неуправляемые ресурсы.

🚩Как он работает

Должен освобождать все неуправляемые ресурсы, занимаемые объектом, а также должен иметь возможность освобождать управляемые ресурсы, если это необходимо. Как правило, управляемые ресурсы освобождаются сами сборщиком мусора, но если управляемый ресурс включает в себя неуправляемые ресурсы, тогда Dispose может быть вызван для их явного освобождения.
public class ResourceHolder : IDisposable
{
private bool disposed = false;

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Освобождение управляемых ресурсов
}
// Освобождение неуправляемых ресурсов
disposed = true;
}
}

~ResourceHolder()
{
Dispose(false);
}
}


Пример использования Dispose
using (var resource = new ResourceHolder())
{
// Использование ресурса
}
// Метод Dispose автоматически вызывается при выходе из блока using


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🤔 Чем Dictionary отличается от ConcurrentDictionary?

- Dictionary — не потокобезопасен, может выдавать исключения при одновременном доступе из разных потоков.
- ConcurrentDictionary — потокобезопасная коллекция, позволяет безопасно читать и изменять данные в многопоточном окружении без внешней синхронизации.
Используется в системах, где возможны параллельные обращения к структуре.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🔥1