C# | Вопросы собесов
5.1K subscribers
34 photos
1 video
1 file
992 links
Download Telegram
🤔 Что такое примитив синхронзиации semaphore?

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

🚩Как работает семафор?

Семафор использует счётчик для отслеживания доступных "разрешений":
Когда поток запрашивает доступ к ресурсу, семафор уменьшает счётчик.
Если счётчик больше нуля, поток получает доступ.
Если счётчик равен нулю, поток блокируется, пока другой поток не освободит ресурс (увеличив счётчик).

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

В .NET часто используется SemaphoreSlim, так как он более лёгкий и эффективный, чем Semaphore.
using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
static SemaphoreSlim semaphore = new SemaphoreSlim(2); // Разрешаем максимум 2 потока одновременно

static async Task AccessResource(int id)
{
Console.WriteLine($"Поток {id} ждёт доступа...");
await semaphore.WaitAsync(); // Захватываем семафор
try
{
Console.WriteLine($"Поток {id} получил доступ!");
await Task.Delay(2000); // Имитация работы с ресурсом
}
finally
{
Console.WriteLine($"Поток {id} освобождает ресурс.");
semaphore.Release(); // Освобождаем семафор
}
}

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


🚩Обычный `Semaphore`

Если нужна синхронизация между разными процессами, можно использовать Semaphore
Semaphore semaphore = new Semaphore(2, 2, "MyGlobalSemaphore");


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

Transient — это самый короткий жизненный цикл.
Новый объект создаётся каждый раз, когда он запрашивается.
Подходит для лёгких, статeless-компонентов, где не требуется запоминание состояния.


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

Метод Finalize() представляет собой специальный метод, который предназначен для выполнения финальной очистки ресурсов перед тем, как объект будет уничтожен сборщиком мусора. Это метод, который может быть определен в классе для очистки неуправляемых ресурсов, если класс не реализует интерфейс IDisposable.

🚩Особенности метода

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

🟠Определение в базовом классе `Object`
Все объекты наследуют от базового класса Object, который предоставляет реализацию Finalize(). Однако в большинстве случаев Finalize() не имеет реализации и не делает ничего, пока не будет переопределен в производном классе.

🟠Замедление сборки мусора
Наличие объектов с финализаторами может замедлить процесс сборки мусора, так как объекты, требующие финализации, должны быть обработаны дважды: сначала они помещаются в очередь финализации, а затем их память освобождается после выполнения Finalize().

class ResourceWrapper
{
// Конструктор
public ResourceWrapper() {
// Инициализация ресурсов
}

// Финализатор
~ResourceWrapper() {
// Код очистки ресурсов
}
}


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

Работа с моделью (например, в
ASP.NET или ORM):
1. Определение модели — создаётся C#-класс с нужными свойствами.
2. Связывание модели — в
ASP.NET модель связывается с формой или JSON из запроса.
3. Валидация модели — используется DataAnnotations или ручная проверка.
4. Применение — модель передаётся в бизнес-логику, сохраняется в базу через ORM, отображается в UI и т.д.
5. Обратная передача — можно вернуть модель обратно на клиент, например, как JSON.
В ORM модель описывает структуру таблицы и связи между сущностями. ORM использует модель для генерации SQL-запросов и маппинга данных.


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

REST (Representational State Transfer) — это архитектурный стиль разработки веб-сервисов, который стал основным методом создания веб-API. Этот стиль был введён Роем Филдингом в его докторской диссертации в 2000 году и основывается на принципах, используемых в протоколе HTTP.

🚩Основные принципы

🟠Client-Server
Архитектура строится на разделении клиента и сервера. Это разделение позволяет разрабатывать клиентскую и серверную части независимо друг от друга, что упрощает разработку и тестирование.

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

🟠Cacheable
Ответы сервера должны быть явно помечены как кэшируемые или некэшируемые, чтобы клиенты могли кэшировать данные и повышать производительность, уменьшая количество запросов к серверу.

🟠Uniform Interface
Важнейший из принципов REST — единый интерфейс, который упрощает и обобщает взаимодействие между клиентом и сервером. Этот интерфейс определяет стандартные методы и форматы обмена информацией, которые должны быть одинаковыми для всех ресурсов. Типичными методами являются GET, POST, PUT, DELETE.

🟠Layered System
Клиент не должен предполагать, что он напрямую соединён с сервером. Между ними может находиться несколько слоёв, таких как балансировщики нагрузки или кэширующие прокси.

🟠Code on Demand (optional)
Серверы могут временно расширять или настраивать функционал на клиентах, передавая им исполняемый код (например, JavaScript).

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

Этот механизм называется интернирование строк (String Interning). Он позволяет хранить одинаковые строковые значения в едином пуле для экономии памяти.


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

Привязка данных (Data Binding) — это механизм, который позволяет автоматически синхронизировать данные между источником (например, моделью) и интерфейсом (например, элементами UI).

🚩Односторонняя привязка (One-Way Binding)

Данные идут только в одном направлении: из модели в UI.
- Для вывода данных, которые не должны изменяться пользователем
- Например, для отображения текущего времени
Пример в WPF
<TextBlock Text="{Binding UserName}" />


🚩Двусторонняя привязка (Two-Way Binding)

Данные синхронизируются в обе стороны: UI ↔️ Модель
- В формах ввода (например, TextBox), чтобы обновлять данные в модели
- Используется в MVVM
Пример в WPF
<TextBox Text="{Binding UserName, Mode=TwoWay}" />


🚩Привязка к событиям (Event Binding)

Позволяет связывать UI с методами обработки событий.
- Для обработки кнопок (Button.Click)
- В реактивных фреймворках (Blazor, WinForms)
Пример в Blazor
<button @onclick="IncrementCount">Добавить</button>

@code {
private int count = 0;
private void IncrementCount() => count++;
}


🚩Привязка к командам (Command Binding)

Используется в паттерне MVVM вместо событий
- В WPF и Xamarin
- Позволяет отделить логику от UI
Пример в WPF
<Button Content="Сохранить" Command="{Binding SaveCommand}" />


🚩Привязка к коллекциям (ItemsSource Binding)

Позволяет привязывать списки к элементам UI (ListBox, DataGrid)
- В списках, таблицах, дропдаунах
Пример в WPF
<ListBox ItemsSource="{Binding Users}" DisplayMemberPath="Name" />


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

В куче объекты разделяются по областям памяти: например, на молодой (Generation 0), средний (Generation 1) и старший (Generation 2) сегменты, чтобы оптимизировать сборку мусора. Также существует разделение на Large Object Heap (для больших объектов) и Small Object Heap.

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

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

🚩Как это работает?

Принимает в качестве параметра объект, который используется в качестве мьютекса (взаимоисключающего объекта). Во время выполнения блока кода внутри lock, текущий поток "захватывает" мьютекс. Если другой поток попытается войти в заблокированный участок кода, используя тот же мьютекс, он будет приостановлен до тех пор, пока первый поток не завершит выполнение блока lock и не освободит мьютекс.
public class Account
{
private decimal balance;
private readonly object balanceLock = new object();

public void Deposit(decimal amount)
{
lock (balanceLock)
{
balance += amount;
}
}

public void Withdraw(decimal amount)
{
lock (balanceLock)
{
if (balance >= amount)
{
balance -= amount;
}
}
}
}


🚩Зачем это нужно?

Без использования lock или других методов синхронизации, программы с многопоточным доступом к общим данным могут испытывать проблемы, такие как гонки и условия гонки (race conditions), когда порядок или время доступа к данным может привести к ошибкам или неожиданным результатам. lock гарантирует, что только один поток может исполнять определенный блок кода, работающий с критическими ресурсами, в любой момент времени.

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

1. Универсальность: позволяет работать с разными источниками данных (массивы, базы данных, XML).
2. Читаемость: код становится компактным и интуитивно понятным.
3. Сильная типизация: ошибки обнаруживаются на этапе компиляции.
4. Оптимизация запросов: для баз данных LINQ к Entity Framework может преобразовывать запросы в SQL.


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

В C# классы могут быть статическими (static) и нестатическими (обычными). Разница в том, как они используются и хранят данные.

🚩Статические классы (`static`)

Не могут создавать объекты (экземпляры)
Содержат только статические (static) методы и поля
Не могут наследоваться и не могут быть унаследованы
Используются для утилитарных методов, глобальных констант и вспомогательных функций
public static class MathHelper
{
public static int Square(int x) => x * x;
}


Использование
int result = MathHelper.Square(5); // 25


🚩Нестатические (обычные) классы
Можно создавать экземпляры (new)
Могут содержать как статические, так и нестатические члены
Можно наследовать от других классов
Используются для работы с данными
public class Car
{
public string Model { get; set; }

public void Drive()
{
Console.WriteLine($"{Model} едет!");
}
}


Использование
Car myCar = new Car { Model = "Tesla" };
myCar.Drive(); // Tesla едет!


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

Групповые делегаты позволяют объединить несколько методов в один вызов.
1. Все методы, входящие в делегат, вызываются последовательно.
2. Применяются для выполнения нескольких операций по одному событию.
3. Это полезно для подписки на события и выполнения цепочки связанных действий.


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

В C# все типы делятся на значимые (value types) и ссылочные (reference types). Основное различие заключается в том, как данные хранятся в памяти и как передаются в методы.

🚩Значимые типы (Value Types)

Хранятся в стеке (Stack).
Передаются по значению (копируются).
Каждый объект имеет свою копию данных.
Не могут быть null (если не использовать Nullable<T>).

🚩Примеры значимых типов:

- int, double, bool, char
- struct, enum, DateTime
int a = 10;
int b = a; // Копия значения
b = 20;

Console.WriteLine(a); // 10 (не изменился)
Console.WriteLine(b); // 20


🚩Ссылочные типы (Reference Types)

Хранятся в куче (Heap), а в стеке лежит ссылка на объект.
Передаются по ссылке (не копируются, а передаётся адрес).
Несколько переменных могут указывать на один и тот же объект.
Могут быть null (если не инициализированы).

class Person
{
public string Name;
}

Person p1 = new Person { Name = "Alice" };
Person p2 = p1; // p2 и p1 указывают на один объект

p2.Name = "Bob";

Console.WriteLine(p1.Name); // Bob (изменилось!)
Console.WriteLine(p2.Name); // Bob


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
🤔 Действительно ли при вызове метода Add уже генерируется SQL-код?

Нет, при вызове метода Add SQL-код еще не генерируется. На этом этапе сущность просто добавляется в контекст, и ее состояние помечается как "добавленное". SQL-код формируется и выполняется только при вызове метода SaveChanges(), который анализирует все изменения и генерирует соответствующие SQL-запросы.


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

Нет, структура (struct) не становится ссылочным типом, даже если мы передаём её через ref или out. Однако, когда структура передаётся с ref или out, передаётся сама структура (по ссылке), а не её копия. Это позволяет изменять исходный объект напрямую, избегая копирования.

🚩Разница между обычной передачей и передачей через `ref`

Передача структуры без ref (по значению, копируется)
struct Point
{
public int X;
public int Y;
}

void ChangePoint(Point p)
{
p.X = 100;
}

Point myPoint = new Point { X = 10, Y = 20 };
ChangePoint(myPoint);

Console.WriteLine(myPoint.X); // 10 (НЕ изменилось, потому что была копия)


Передача структуры с ref (по ссылке, изменения сохраняются)
void ChangePointRef(ref Point p)
{
p.X = 100;
}

ChangePointRef(ref myPoint);

Console.WriteLine(myPoint.X); // 100 (значение изменилось)


🚩Что насчёт `out`?

out работает так же, как ref, но требует обязательной инициализации внутри метода.
void InitPoint(out Point p)
{
p = new Point { X = 50, Y = 50 }; // Обязательно присвоить значение
}

Point newPoint;
InitPoint(out newPoint);

Console.WriteLine(newPoint.X); // 50


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

Interceptor — это механизм, позволяющий вмешиваться в выполнение операций (например, запросов, логики работы, логирования) до или после их исполнения.
В .NET и EF Core interceptors применяются для:
- Логирования SQL-запросов
- Модификации поведения БД
- Аудита действий
Это своего рода «прослойка» между системой и реальным выполнением.


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

Сборщик мусора (Garbage Collector, GC) в .NET автоматически управляет памятью, освобождая неиспользуемые объекты.

🚩Как запускается GC?

🟠Автоматически (по мере необходимости)
GC сам решает, когда запуститься, исходя из:
Заполнения памяти (Heap почти полный)
Недостатка ресурсов (мало RAM)
Давления на систему
class Program
{
static void Main()
{
for (int i = 0; i < 100000; i++)
{
var obj = new object(); // Создаётся много объектов
} // После выхода из цикла ненужные объекты освобождаются GC
}
}


🟠Вручную (`GC.Collect()`)
Можно форсировать сборку мусора, но это редко рекомендуется**, так как GC сам лучше решает, когда запускаться.
GC.Collect(); // Принудительный запуск сборщика мусора
GC.WaitForPendingFinalizers(); // Дождаться завершения финализаторов


🟠Через `using` и `Dispose()` (IDisposable)
GC не сразу удаляет объекты с ресурсами (файлы, сокеты).
Такие объекты лучше очищать вручную через Dispose() или using.
using (StreamWriter writer = new StreamWriter("file.txt"))
{
writer.WriteLine("Привет, мир!");
} // `Dispose()` вызовется автоматически


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

Оператор new:
- создаёт экземпляр класса или структуры;
- выделяет память в куче или стеке (в зависимости от типа);
- вызывает конструктор — по умолчанию или переданный;
- возвращает ссылку на объект (для reference-type) или сам объект (для value-type).


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥1💊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
👍3🔥1
🤔 Какие есть типы данных в .NET?

В .NET типы делятся на две большие категории:
- Значимые (Value types): хранят данные непосредственно.
- Примитивы: int, double, bool, char
- Структуры: DateTime, Guid, пользовательские struct
- enum — перечисления
- Ссылочные (Reference types): содержат ссылку на данные, которые лежат в куче.
- Классы (class)
- Интерфейсы (interface)
- Делегаты
- Массивы
- string (особенность: неизменяем, но ссылочный)


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

🚩Виды

🟠Юнит-тесты
Предназначены для проверки отдельных компонентов или модулей приложения в изоляции. Они помогают убедиться, что отдельные функции или методы работают правильно.
Цель: Проверка логики отдельных методов или классов.
Инструменты: xUnit, NUnit, MSTest.
using Xunit;

public class CalculatorTests
{
[Fact]
public void Add_SimpleValues_ReturnsSum()
{
var calculator = new Calculator();
var result = calculator.Add(2, 3);
Assert.Equal(5, result);
}
}

public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
}


🟠Интеграционные тесты
Проверяют взаимодействие между различными компонентами системы, убеждаясь, что они корректно работают вместе.
Цель: Проверка взаимодействия между модулями.
Инструменты: xUnit, NUnit, MSTest, плюс дополнительные библиотеки для тестирования баз данных или HTTP-запросов.
using System.Net.Http;
using System.Threading.Tasks;
using Xunit;

public class IntegrationTests
{
private readonly HttpClient _client;

public IntegrationTests()
{
var appFactory = new CustomWebApplicationFactory<Startup>();
_client = appFactory.CreateClient();
}

[Fact]
public async Task Get_EndpointReturnsSuccessAndCorrectContentType()
{
var response = await _client.GetAsync("/api/values");
response.EnsureSuccessStatusCode();
Assert.Equal("application/json; charset=utf-8", response.Content.Headers.ContentType.ToString());
}
}


🟠Функциональные тесты
Проверяют, что приложение выполняет свои функции в соответствии с требованиями. Эти тесты проверяют конкретные сценарии использования.
Цель: Проверка функциональности приложения на уровне пользователя.
Инструменты: Selenium, Playwright, Cypress.
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using Xunit;

public class UiTests
{
[Fact]
public void LoadPage_CheckTitle()
{
using (IWebDriver driver = new ChromeDriver())
{
driver.Navigate().GoToUrl("https://example.com");
Assert.Equal("Example Domain", driver.Title);
}
}
}


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

🟠Приемочные тесты
Проводятся для проверки, что приложение соответствует требованиям и готово к использованию клиентом или конечным пользователем.
Цель: Подтверждение соответствия приложения требованиям.
Инструменты: Cucumber, SpecFlow (для BDD).

🟠Регрессионные тесты
Проверяют, что недавние изменения в коде не нарушили существующую функциональность.
Цель: Убедиться, что новые изменения не привели к новым багам.
Инструменты: Все инструменты для юнит-тестирования и функционального тестирования.

🟠Нагрузочные тесты
Проверяют, как приложение ведет себя под нагрузкой, например, при большом количестве одновременных пользователей или операций.
Цель: Оценка производительности и устойчивости приложения под нагрузкой.
Инструменты: JMeter, Gatling, Apache Bench.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2