C# | Вопросы собесов
5.1K subscribers
36 photos
1 file
988 links
Download Telegram
🤔 В чем разница между семафором и mutex?

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


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 В чем отличие slim версий от обычных семафоров?

Semaphore – классический семафор, использующий ядро операционной системы для синхронизации потоков.
SemaphoreSlim – более лёгкая и быстрая версия, работающая в основном на уровне управляемого кода без вызовов ядра ОС.

🚩Когда использовать `Semaphore`, а когда `SemaphoreSlim`?

Используйте Semaphore, если:
Вам нужно разделение ресурсов между разными процессами.
Вы работаете с нативным кодом или сторонними API, использующими семафоры ОС.

Используйте SemaphoreSlim, если:
Вам нужна быстрая блокировка между потоками в одном процессе.
Вы хотите использовать асинхронный код (async/await).
Вам важна производительность.

🚩Пример использования `Semaphore` (между процессами и потоками)

using System;
using System.Threading;

class Program
{
static Semaphore semaphore = new Semaphore(2, 2); // Макс. 2 потока могут войти одновременно

static void Main()
{
for (int i = 1; i <= 5; i++)
{
new Thread(DoWork).Start(i);
}
}

static void DoWork(object id)
{
Console.WriteLine($"Поток {id} ждёт семафор...");
semaphore.WaitOne(); // Захватываем семафор

Console.WriteLine($"Поток {id} выполняет работу...");
Thread.Sleep(2000); // Симуляция работы

Console.WriteLine($"Поток {id} освобождает семафор");
semaphore.Release(); // Освобождаем семафор
}
}


🚩Пример использования `SemaphoreSlim` (быстрее, поддерживает `async/await`)

using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(2); // 2 потока одновременно

static async Task Main()
{
Task[] tasks = new Task[5];
for (int i = 0; i < 5; i++)
{
tasks[i] = DoWork(i);
}
await Task.WhenAll(tasks);
}

static async Task DoWork(int id)
{
Console.WriteLine($"Задача {id} ждёт семафор...");
await semaphoreSlim.WaitAsync(); // Асинхронное ожидание

Console.WriteLine($"Задача {id} выполняет работу...");
await Task.Delay(2000); // Симуляция работы

Console.WriteLine($"Задача {id} освобождает семафор");
semaphoreSlim.Release(); // Освобождаем семафор
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯1
🤔 Как middleware возвращает ответ?

Это промежуточное ПО, которое обрабатывает HTTP-запросы и формирует HTTP-ответы. Оно либо обрабатывает запрос самостоятельно, либо передаёт его следующему middleware в цепочке. Например, в ASP.NET middleware может перехватить запрос, выполнить аутентификацию, и только потом передать управление дальше.

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

Extension-методы (методы расширения) — это способ добавить новые методы к существующим классам, не изменяя их код и не создавая наследников. Они позволяют расширять классы и интерфейсы, даже если у нас нет доступа к их исходному коду.

🚩Как работают extension-методы?

Это обычные статические методы, но объявленные внутри статического класса.
Первый параметр метода должен принимать тот тип, который мы хотим расширить, и перед ним ставится ключевое слово this.
После этого метод становится доступен как "встроенный" у этого типа.

🟠Добавляем метод к `string`
Допустим, у нас есть строка, и мы хотим добавить метод ToSnakeCase, который заменяет пробелы на нижние подчеркивания.
using System;

public static class StringExtensions
{
public static string ToSnakeCase(this string str)
{
return str.Replace(" ", "_").ToLower();
}
}

class Program
{
static void Main()
{
string text = "Hello World";
Console.WriteLine(text.ToSnakeCase()); // hello_world
}
}


🟠Расширяем `List<int>`
Добавим метод `SumEvenNumbers()`, который суммирует только четные числа в List<int>.
using System;
using System.Collections.Generic;
using System.Linq;

public static class ListExtensions
{
public static int SumEvenNumbers(this List<int> numbers)
{
return numbers.Where(n => n % 2 == 0).Sum();
}
}

class Program
{
static void Main()
{
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6 };
Console.WriteLine(numbers.SumEvenNumbers()); // 12 (2 + 4 + 6)
}
}


🚩Когда использовать extension-методы?

Когда нужно добавить новый метод к существующему классу, но нельзя изменить его код (например, string, List<T>, DateTime).
Когда хочется сделать код более читаемым: numbers.SumEvenNumbers() лучше, чем MyExtensions.SumEvenNumbers(numbers).
Когда нужно улучшить API без наследования и изменения структуры классов.

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

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


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

Это технология, обеспечивающая двустороннюю связь между клиентом и сервером через один TCP-соединение. В отличие от традиционного HTTP, который работает по принципу запрос-ответ, WebSockets позволяют передавать данные в обоих направлениях в режиме реального времени, что делает их идеальными для приложений, требующих мгновенного обмена данными.

🚩Характеристики

🟠Двусторонняя связь
Клиент и сервер могут отправлять данные друг другу независимо, без необходимости инициировать новый запрос.

🟠Постоянное соединение
После установления WebSocket-соединение остается открытым, что позволяет передавать данные с минимальной задержкой.

🟠Эффективность
Меньшие накладные расходы по сравнению с HTTP, так как заголовки передаются только при установлении соединения, а не для каждого сообщения.

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

🚩Как работают

1⃣Установка соединения
Клиент инициирует соединение с сервером через HTTP-запрос с заголовком Upgrade, указывая, что он хочет перейти на WebSocket-протокол.
2⃣Рукопожатие (handshake)
Сервер отвечает согласием на переход на WebSocket-протокол, и соединение устанавливается.
3⃣Обмен данными
После установления соединения данные могут передаваться в обоих направлениях до тех пор, пока одно из сторон не закроет соединение.

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

Сервер на Python с использованием библиотеки websockets
import asyncio
import websockets

async def handler(websocket, path):
async for message in websocket:
print(f"Received message: {message}")
await websocket.send(f"Echo: {message}")

start_server = websockets.serve(handler, "localhost", 8765)

asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()


Клиент на JavaScript
const socket = new WebSocket('ws://localhost:8765');

socket.onopen = function(event) {
console.log('WebSocket is open now.');
socket.send('Hello, Server!');
};

socket.onmessage = function(event) {
console.log(`Message from server: ${event.data}`);
};

socket.onclose = function(event) {
console.log('WebSocket is closed now.');
};

socket.onerror = function(error) {
console.log(`WebSocket error: ${error}`);
};


🚩Плюсы

Реальное время
Подходит для приложений, где важна минимальная задержка, таких как чаты, игровые приложения и финансовые торговые платформы.
Меньшие накладные расходы
Меньшее количество данных передается по сети по сравнению с традиционными HTTP-запросами.
Удобство
Простота в использовании и поддержка большинством современных браузеров.

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

В Entity Framework join реализуется через LINQ-запросы. Это позволяет объединять данные из разных таблиц на основе ключей. Например, через join или навигационные свойства можно связать данные из связанных сущностей.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7😁2🔥1🤯1
🤔 Расскажи про конкурентные коллекции?

Конкурентные коллекции — это специализированные коллекции, которые обеспечивают безопасное выполнение операций в многопоточной среде. В стандартной библиотеке .NET существуют несколько типов таких коллекций, каждая из которых предназначена для различных сценариев использования. Давайте рассмотрим основные из них.

🟠ConcurrentDictionary<TKey, TValue>
Это словарь, который позволяет безопасно добавлять, удалять и изменять элементы из нескольких потоков одновременно. Он реализует интерфейс IDictionary<TKey, TValue>.
var concurrentDictionary = new ConcurrentDictionary<int, string>();
concurrentDictionary.TryAdd(1, "value1");
concurrentDictionary.TryAdd(2, "value2");

string value;
if (concurrentDictionary.TryGetValue(1, out value))
{
Console.WriteLine(value); // Output: value1
}


🟠ConcurrentQueue<T>
Это очередь, которая обеспечивает безопасное добавление элементов в конец и извлечение из начала в многопоточной среде. Она реализует интерфейс IProducerConsumerCollection<T>.
var concurrentQueue = new ConcurrentQueue<int>();
concurrentQueue.Enqueue(1);
concurrentQueue.Enqueue(2);

int result;
if (concurrentQueue.TryDequeue(out result))
{
Console.WriteLine(result); // Output: 1
}


🟠ConcurrentStack<T>
Это стек, который обеспечивает безопасное добавление и извлечение элементов в многопоточной среде. Он также реализует интерфейс IProducerConsumerCollection<T>.
var concurrentStack = new ConcurrentStack<int>();
concurrentStack.Push(1);
concurrentStack.Push(2);

int result;
if (concurrentStack.TryPop(out result))
{
Console.WriteLine(result); // Output: 2
}


🟠ConcurrentBag<T>
Это коллекция, которая позволяет безопасно добавлять и извлекать элементы в многопоточной среде. Она не гарантирует порядок элементов, поэтому используется в случаях, когда порядок не имеет значения.
var concurrentBag = new ConcurrentBag<int>();
concurrentBag.Add(1);
concurrentBag.Add(2);

int result;
if (concurrentBag.TryTake(out result))
{
Console.WriteLine(result); // Output: 1 или 2
}


🟠BlockingCollection<T>
Это коллекция, которая поддерживает ограниченную емкость и блокировку потоков при добавлении или извлечении элементов. Она особенно полезна для реализации паттернов продюсер-потребитель.
var blockingCollection = new BlockingCollection<int>(boundedCapacity: 5);
Task.Run(() =>
{
for (int i = 0; i < 10; i++)
{
blockingCollection.Add(i);
Console.WriteLine($"Added {i}");
}
blockingCollection.CompleteAdding();
});

foreach (var item in blockingCollection.GetConsumingEnumerable())
{
Console.WriteLine($"Consumed {item}");
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍61
Forwarded from easyoffer
💡 В EasyOffer 2.0 появится фильтрация вопросов по грейдам и типам интервью!

📊 Например, вот вероятности ТОП-30 вопросов, которые задают на HR-скрининге Python-разработчику уровня Middle/Senior. Данные основаны на 53 реальных интервью.

97% Какие у тебя зарплатные ожидания
73% Какие у тебя есть вопросы
44% Какие критерии при выборе будущей работы
41% Расскажи о себе
38% Почему ищешь работу
35% Расскажи про свой опыт
35% Расскажи про проект на предыдущей работе
32% Почему уволился с предыдущей работы
29% Где территориально сейчас живешь/находишься
23% Есть ли другие предложения по работе
17% Есть ли военный билет
17% Почему хочешь сменить работу
17% Как проводишь свободное время
17% Расскажи про задачи на предыдущей работе
17% Сколько коммерческого опыта работы с Python
17% С какими БД работал
14% Находишься ли в активном поиске работы
14% С каким стеком работаешь
14% Почему решил откликнуться на нашу вакансию
14% Какой текущий статус поиска работы
11% Почему решил стать программистом
11% С какими фреймворками работал
11% Какую зарплату получал на предыдущей работе
11% Работаешь ли в настоящий момент
11% На какой грейд себя оцениваешь
11% Как быстро можешь приступить к работе после получения офера
11% Расскажи про свои pet-проекты
8% Какие знаешь типы данных в Python
8% Что такое декоратор в Python
8% Что ищешь на новой работе

🚀 Скоро стартует краудфандинговая кампания, которая поможет ускорить разработку EasyOffer 2.0.
Первые спонсоры получат уникальные лимитированные награды!

📢 Если вам это интересно, подписывайтесь на канал 👉 этот телеграм канал
🤔1
🤔 Если в двух переменных хранится одинаковое значение, то будут ли они равны?

Равенство переменных зависит от их типа:
- Для примитивных типов, таких как int, double, значения сравниваются напрямую.
- Для ссылочных типов сравниваются ссылки (адреса в памяти), если метод Equals не переопределён.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11
🤔 Когда можно использовать 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
7👍1
🤔 Что надо сделать, чтобы сравнить коллекции по содержимому?

Для сравнения содержимого коллекций можно использовать метод SequenceEqual. Также важно, чтобы элементы коллекции имели корректно переопределённые методы Equals и GetHashCode, если они являются пользовательскими объектами.

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

Индексы в базах данных, таких как SQL Server, MySQL или PostgreSQL, существенно улучшают производительность запросов, особенно для операций поиска, сортировки и фильтрации. Однако у индексов есть и минусы, которые могут негативно сказаться на производительности и других аспектах работы базы данных.

🟠Увеличение времени записи
Индексы замедляют операции вставки (INSERT), обновления (UPDATE) и удаления (DELETE), так как при каждом изменении данных необходимо также обновлять индексы.
Вставка: При вставке новой записи нужно обновить все соответствующие индексы.
Обновление: При обновлении записи могут изменяться индексируемые колонки, что требует обновления индексов.
Удаление: При удалении записи нужно удалить соответствующие записи из индексов.

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

🟠Замедление операций массовой загрузки данных
При массовой загрузке данных, например, при использовании операций LOAD DATA или BULK INSERT, наличие индексов замедляет процесс, так как индексы должны обновляться по мере добавления каждой записи.

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

🟠Сложность управления
Управление индексами требует дополнительного администрирования и мониторинга. Нужно следить за эффективностью индексов, удалять неиспользуемые индексы и создавать новые по мере изменения запросов и структуры данных.

🟠Перекрестные индексы
Наличие нескольких индексов на одной таблице может привести к конфликтам при планировании запросов. Оптимизатор запросов может выбирать менее эффективные индексы, что ухудшает производительность.

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

🚩Пример ситуации

CREATE TABLE Employees (
EmployeeID INT PRIMARY KEY,
FirstName VARCHAR(50),
LastName VARCHAR(50),
DepartmentID INT,
Salary DECIMAL(10, 2)
);

CREATE INDEX idx_firstname ON Employees(FirstName);
CREATE INDEX idx_lastname ON Employees(LastName);
CREATE INDEX idx_department ON Employees(DepartmentID);


🚩Минусы

Вставка данных
INSERT INTO Employees (EmployeeID, FirstName, LastName, DepartmentID, Salary)
VALUES (1, 'John', 'Doe', 10, 60000.00);


Обновление данных
UPDATE Employees
SET Salary = Salary * 1.05
WHERE DepartmentID = 10;


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

Класс должен переопределять методы Equals и GetHashCode, чтобы гарантировать уникальность ключей в коллекциях, таких как Dictionary или HashSet.

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

В C# и .NET память управляется сборщиком мусора (Garbage Collector, GC), который делит объекты на три поколения

🟠Generation 0 (Gen 0, нулевое поколение)
самые "молодые" объекты.
🟠Generation 1 (Gen 1, первое поколение)
промежуточные объекты.
🟠Generation 2 (Gen 2, второе поколение)
"долгоживущие" объекты.

🚩Какие объекты попадают в Generation 0?

В Gen 0 живут "короткоживущие" объекты которые создаются и быстро уничтожаются.
Это новые объекты, которые только что были выделены в управляемой куче (Heap).
Обычно это локальные переменные внутри методов, если они не выходят за их пределы.

Пример объектов в Gen 0
class Program
{
static void Main()
{
for (int i = 0; i < 5; i++)
{
var obj = new object(); // Этот объект создаётся в Gen 0
}

GC.Collect(); // Принудительный запуск GC для проверки
}
}


🚩Когда объекты остаются в Gen 0, а когда переходят в следующее поколение?

Если объект быстро умирает → удаляется из Gen 0 при первой же очистке.
Если объект выжил после первой очистки GC → переходит в Gen 1.
Если объект живёт долго → может попасть в Gen 2.

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

Для получения значения по ключу в коллекциях, таких как Dictionary, используется индексатор, например, dictionary[key]. Чтобы избежать исключений при отсутствии ключа, можно использовать метод TryGetValue.

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

Value Type (тип значения) – это тип данных, который хранит своё значение непосредственно в памяти (обычно в стеке), а не ссылку на объект в куче (heap), как это делает ссылочный тип (Reference Type).

🚩Какие типы данных являются Value Type?

Простые типы (int, double, bool, char, byte, float, decimal, etc.)
Структуры (struct)
Перечисления (enum)
Nullable-значения (int?, double?)

🚩Пример Value Type

int a = 10;
int b = a; // Значение копируется

b = 20;
Console.WriteLine(a); // 10 (остался неизменным)
Console.WriteLine(b); // 20


🚩Где хранятся Value Type?

Value Type обычно хранятся в стеке (stack) – это быстрая область памяти.
Если структура (struct) является частью объекта (который хранится в куче), то её значение хранится внутри объекта в куче.
struct Point
{
public int X;
public int Y;
}

class Program
{
static void Main()
{
Point p1 = new Point { X = 5, Y = 10 };
Point p2 = p1; // Копирование структуры (создаётся новый экземпляр)

p2.X = 20;
Console.WriteLine(p1.X); // 5 (остался неизменным)
Console.WriteLine(p2.X); // 20
}
}


🚩Когда использовать Value Type?

Если данные небольшие и часто изменяются – struct
Если объект недолговечный и не требует сложного поведения
Если производительность важна – Value Type быстрее из-за работы в стеке

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Как реализовать «один ко многим»?

Связь «один ко многим» реализуется через внешний ключ в таблице, хранящей несколько записей, относящихся к одной сущности. В объектно-ориентированном программировании один объект может содержать список связанных объектов, что отражает логическую связь между ними.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🤔1
🤔 Что делает new 'имя объекта'()?

Оператор new в C# создаёт новый экземпляр объекта и выделяет для него память в куче (Heap) или стеке (Stack), в зависимости от типа.

🚩Как работает `new`?

Для классов (class) – выделяет память в куче (Heap) и возвращает ссылку на объект.
Для структур (struct) – если структура создаётся без new, её поля остаются неинициализированными, но если использовать new, она получает значения по умолчанию.
Для массивов (T[]) – выделяет память в куче, даже если T – это struct.
Для делегатов – создаёт экземпляр делегата.

Пример: new с классом (class)
class Person
{
public string Name;

public Person(string name)
{
Name = name;
}
}

class Program
{
static void Main()
{
Person p1 = new Person("Alice"); // Создаём новый объект в куче
Console.WriteLine(p1.Name); // Alice
}
}


Пример: new со структурой (struct)
struct Point
{
public int X;
public int Y;

public Point(int x, int y)
{
X = x;
Y = y;
}
}

class Program
{
static void Main()
{
Point p1 = new Point(5, 10); // Создаёт структуру в стеке
Console.WriteLine(p1.X); // 5
}
}


Пример: new с массивом
int[] numbers = new int[5]; // Создаёт массив в куче
numbers[0] = 10;
Console.WriteLine(numbers[0]); // 10


🚩Что делает `new` за кулисами?

Выделение памяти в куче (для классов) или в стеке (для структур).
Вызов конструктора класса или структуры.
Возвращение ссылки на объект (для классов) или самого объекта (для структур).

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
🤔 Как реализовать «многие ко многим»?

Связь «многие ко многим» требует создания промежуточной таблицы, которая содержит пары идентификаторов связанных объектов. В объектно-ориентированном программировании используются коллекции объектов, хранящие ссылки друг на друга, что обеспечивает гибкость взаимодействия.


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