C# | Вопросы собесов
5.1K subscribers
36 photos
1 file
990 links
Download Telegram
🤔 Что известно про парадигмы и принципы ООП?

Объектно-ориентированное программирование (ООП) основано на четырёх ключевых парадигмах: инкапсуляция, наследование, полиморфизм и абстракция. Оно позволяет строить гибкие и масштабируемые системы. Принципы ООП включают SOLID, GRASP и DRY/KISS/YAGNI.


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

HashSet<T> — это коллекция уникальных элементов, которая обеспечивает быстрый поиск, добавление и удаление. В основе HashSet<T> лежит хеш-таблица, что делает операции очень быстрыми (почти за O(1) в среднем случае).

🚩Создание и использование `HashSet<T>`

Простой пример
HashSet<int> numbers = new HashSet<int> { 1, 2, 3, 4, 5 };

// Добавление элементов (дубликаты не добавляются)
numbers.Add(3); // Уже есть в HashSet, не добавится
numbers.Add(6); // Добавится

// Вывод всех элементов
foreach (int num in numbers)
{
Console.Write(num + " ");
}


Вывод
1 2 3 4 5 6


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

Пример работы с Contains и Remove
if (numbers.Contains(3))
{
numbers.Remove(3);
}

Console.WriteLine(string.Join(", ", numbers));


Вывод
1, 2, 4, 5, 6


🚩Операции над множествами

HashSet<T> поддерживает математические операции над множествами, такие как пересечение, объединение и разность.

Пересечение (IntersectWith)
HashSet<int> set1 = new HashSet<int> { 1, 2, 3, 4 };
HashSet<int> set2 = new HashSet<int> { 3, 4, 5, 6 };

set1.IntersectWith(set2); // Оставит только {3, 4}
Console.WriteLine(string.Join(", ", set1));


Вывод
3, 4


Объединение (UnionWith)
set1 = new HashSet<int> { 1, 2, 3 };
set2 = new HashSet<int> { 3, 4, 5 };

set1.UnionWith(set2); // set1 = {1, 2, 3, 4, 5}
Console.WriteLine(string.Join(", ", set1));


Вывод
1, 2, 3, 4, 5


Разность (ExceptWith)
set1 = new HashSet<int> { 1, 2, 3, 4, 5 };
set2 = new HashSet<int> { 3, 4 };

set1.ExceptWith(set2); // Удалит {3, 4}, останется {1, 2, 5}
Console.WriteLine(string.Join(", ", set1));


Вывод
1, 2, 5


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

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


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

Это метод интерфейса IDisposable, предназначенный для явного освобождения неуправляемых ресурсов, таких как файловые дескрипторы, сокеты или подключение к базе данных. Его нужно вызывать вручную (или через using), чтобы предотвратить утечки памяти и других ресурсов.

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

При выполнении программных задач можно выделить два типа нагрузок:

I/O-bound (ограничение ввода-вывода)
CPU-bound (ограничение процессора)

🚩I/O-bound (ограничение ввода-вывода)

Основная проблема: программа ждет завершения операций ввода-вывода (диска, сети, базы данных, файловой системы и т. д.), а не загружает процессор.
Примеры:
- Чтение и запись файлов на диск
- Запросы к базе данных
- HTTP-запросы к API
- Чтение данных из сети
Решение: Использование асинхронного программирования (async/await), чтобы не блокировать поток.
public async Task<string> FetchDataAsync()
{
using HttpClient client = new HttpClient();
return await client.GetStringAsync("https://example.com");
}


🚩CPU-bound (ограничение процессора)

Основная проблема: процессор сильно загружен вычислениями, и узким местом становится скорость обработки данных, а не ввод-вывод.
Примеры:
- Генерация больших отчетов
- Кодирование/декодирование видео
- Комплексные математические вычисления
- Сортировка больших массивов
public static long CalculateFactorial(int number)
{
return Enumerable.Range(1, number).Aggregate(1, (a, b) => a * b);
}

public async Task<long> ComputeAsync(int number)
{
return await Task.Run(() => CalculateFactorial(number));
}


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

Это HTTP-метод, используемый для отправки данных на сервер.
1. Передаёт данные в теле запроса, что делает его подходящим для отправки больших или конфиденциальных данных.
2. Используется для операций, которые изменяют состояние сервера, например, создание новых ресурсов.


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

Блок using используется для управления временем жизни объектов, которые потребляют неуправляемые ресурсы, такие как файлы, соединения с базой данных или сетевые соединения. Основное преимущество использования блока using заключается в автоматическом освобождении этих ресурсов, что помогает предотвратить утечки ресурсов и улучшить управление памятью.

🚩Основные преимущества блока

🟠Автоматическое освобождение ресурсов
Блок using гарантирует, что метод Dispose() будет вызван автоматически, когда выполнение кода выйдет из блока using, даже если возникнет исключение. Это освобождает программиста от необходимости вручную вызывать Dispose() и уменьшает вероятность ошибок.
using (StreamReader reader = new StreamReader("file.txt"))
{
string content = reader.ReadToEnd();
Console.WriteLine(content);
}
// StreamReader автоматически закрывается и освобождает ресурсы после выхода из блока using.


🟠Сокращение количества кода
Использование блока using уменьшает количество необходимого кода для обеспечения правильного освобождения ресурсов.
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
// Работа с базой данных
}
// SqlConnection автоматически закрывается и освобождает ресурсы после выхода из блока using.


🟠Повышенная надежность
Блок using повышает надежность кода, так как гарантирует, что ресурсы будут освобождены даже в случае возникновения исключений.
try
{
using (StreamWriter writer = new StreamWriter("file.txt"))
{
writer.WriteLine("Hello, World!");
}
}
catch (Exception ex)
{
Console.WriteLine($"Произошла ошибка: {ex.Message}");
}
// StreamWriter автоматически закрывается и освобождает ресурсы после выхода из блока using, даже если произошла ошибка.


🟠Чистый и понятный код
Код, использующий блок using, выглядит более чистым и упрощает понимание и сопровождение.
using (MemoryStream memoryStream = new MemoryStream())
{
// Работа с MemoryStream
}
// MemoryStream автоматически освобождается после выхода из блока using.


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

Работа с файлами
using System;
using System.IO;

class Program
{
static void Main()
{
using (StreamReader reader = new StreamReader("example.txt"))
{
string content = reader.ReadToEnd();
Console.WriteLine(content);
}
// StreamReader автоматически закрывается и освобождает ресурсы после выхода из блока using.
}
}


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

Используется CancellationToken:
1. Создаётся CancellationTokenSource.
2. В метод передаётся токен.
3. При отмене — токен сигнализирует завершение задачи.


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

Метод set в контексте чаще всего используется в свойствах (properties) класса и служит для установки значения свойства. Он работает как часть автоматического или пользовательского свойства, позволяя контролировать, что происходит, когда свойству присваивается значение.

🚩Что такое свойство?

Свойство (property) в C# – это синтаксический сахар, который позволяет обращаться к полям класса как к переменным, но при этом добавляет возможность добавлять логику для получения (get) и установки (set) значений.
public class Person
{
private string name; // Закрытое поле

public string Name // Свойство
{
get { return name; } // Получить значение
set { name = value; } // Установить значение
}
}


🚩Зачем нужен метод `set`?

🟠Контролировать логику установки значений
Например, вы можете ограничить, какие значения можно присваивать.

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

🟠Защищать данные
Вы можете использовать метод set для проверки значений на валидность или ограничения доступа (например, сделать его приватным).

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

Проверка входных данных:
public class Person
{
private int age;

public int Age
{
get { return age; }
set
{
if (value < 0)
{
throw new ArgumentException("Возраст не может быть отрицательным.");
}
age = value;
}
}
}


Только для чтения
Вы можете сделать set приватным, чтобы свойство можно было только читать извне:
public class Person
{
public string Name { get; private set; }

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


Автоматические свойства
Если вам не нужна дополнительная логика, можно использовать автоматические свойства
public class Person
{
public string Name { get; set; } // Автоматически создаются get и set
}


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

Нулевое поколение (Generation 0) — это область памяти, куда помещаются все новые объекты, когда они только создаются.
Туда попадают:
- Все новые экземпляры классов.
- Краткоживущие объекты (например, временные строки, коллекции и т.п.).


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

Ключи должны быть:
- Уникальными
- Иметь устойчивую реализацию GetHashCode() и Equals()
Подходящие типы:
- Примитивы (int, string, GUID и т.п.)
- Структуры (например, кастомные value types)
- Объекты (если правильно переопределены Equals и GetHashCode)


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

Да, порядок catch имеет значение!
Исключения проверяются сверху вниз, и первый подходящий catch будет выполнен.

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

1. Исключение проверяется по порядку catch-блоков.
2. Если catch подходит → он выполняется, остальные игнорируются.
3. Специфичные исключения (DivideByZeroException) нужно ставить выше общих (Exception).

🚩Ошибка: общий `catch` выше специфичных

Так делать нельзя!
try
{
int x = 5 / 0; // Ошибка
}
catch (Exception ex) // Ловит все исключения
{
Console.WriteLine("Общая ошибка");
}
catch (DivideByZeroException ex) // Никогда не выполнится!
{
Console.WriteLine("Деление на ноль!");
}


Правильный порядок catch
try
{
int x = 5 / 0;
}
catch (DivideByZeroException ex) // Специфичный `catch` первым
{
Console.WriteLine("Ошибка: деление на ноль!");
}
catch (Exception ex) // Общий `catch` внизу
{
Console.WriteLine("Произошла ошибка!");
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Может ли быть несколько блоков catch?

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

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

Когда человек вводит логин и пароль, система аутентифицирует его, проверяя, действительно ли это тот, за кого он себя выдаёт.

🚩Как работает аутентификация?

Пользователь вводит данные (например, логин и пароль).
Система проверяет их в базе данных.
Если данные верны → доступ разрешён.
Если данные неверны → отказ в доступе.

public async Task<IActionResult> Login(string username, string password)
{
var user = await _userManager.FindByNameAsync(username);
if (user != null && await _userManager.CheckPasswordAsync(user, password))
{
await _signInManager.SignInAsync(user, isPersistent: false);
return RedirectToAction("Index", "Home");
}
ModelState.AddModelError("", "Неверный логин или пароль");
return View();
}


🚩Виды аутентификации

🟠По паролю
Самый распространённый вариант. Минус: если пароль украден – доступ открыт.
🟠Двухфакторная (2FA)
Например, SMS-код + пароль. Усложняет взлом аккаунта.
🟠Биометрическая
Отпечаток пальца, Face ID. Удобно, но требует спецоборудования.
🟠OAuth (Google, Facebook, GitHub)
Вход через соцсети. Удобно, не нужно запоминать пароль.
🟠Аутентификация по токену (JWT)
Используется в API и микросервисах. Позволяет работать без сохранения сессий.

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

Связи бывают: один к одному, один ко многим, многие ко многим. Они определяют, как таблицы взаимодействуют друг с другом через ключи.

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

В 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
👍3
🤔 В чём разница между Count и Capacity?

- Count — фактическое количество элементов, хранящихся в коллекции.
- Capacity — внутренняя ёмкость, то есть сколько элементов может поместиться до перераспределения памяти.
Capacity всегда больше или равно Count. Увеличение Count сверх Capacity приводит к перераспределению памяти.


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

Используется для:
- Параллельного доступа к словарю без блокировок.
- Поддержки безопасных операций чтения и записи (например, TryAdd, TryUpdate, AddOrUpdate).
- Повышения производительности при работе с данными в многопоточном приложении (например, при кэшировании, обработке запросов и событий).
Это ключевая структура в системах с высокой конкурентной нагрузкой.


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