C# | Вопросы собесов
СтатистикаСайт: https://easyoffer.ru/ Все каналы: t.me/+xGeAw6ckJ4liYzQy Контакт для рекламы: @easyoffer_adv
- Последний пост
- 12:01
- Последнее чтение
- 00:29
- Постов за неделю
- 9
- Всего постов
- 25
- Тип
- открытый
- Язык
- русский
- Категория
- Технологии (по похожим)
- В каталоге с
- 12 авг.
- 1/24сутки в ленте
- 400
- 1/48двое суток
- 458
- 1/72трое суток
- 494
Оценка по просмотрам недавних постов: пост набирает почти всё за первые сутки.
Посты
видео или голосовое, без подписи
🤔 Зачем сделали 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 полезен для методов, которые должны вернуть несколько значений или инициализировать объекты, которые не могут быть инициализированы заранее. Ставь 👍 и забирай 📚 Базу знаний
🤔 Какой слой rest и swap с точки зрения трехслойной архитектуры? В трехслойной архитектуре (трехуровневая архитектура), также известной как многоуровневая архитектура, приложения разделяются на три логических слоя: 🟠Презентационный слой (Presentation Layer) Отвечает за взаимодействие с пользователем. Веб-интерфейсы, мобильные приложения, десктопные приложения. Примеры: HTML/CSS/JavaScript для веб-приложений, UI-компоненты в мобильных и десктопных приложениях. 🟠Логический слой (Business Logic Layer) Содержит бизнес-логику и правила приложения. Обрабатывает данные, выполняет вычисления, применяет бизнес-правила. Примеры: классы и методы, реализующие бизнес-логику, сервисы, обработчики данных. 🟠Слой данных (Data Access Layer): Отвечает за взаимодействие с источниками данных. Операции с базами данных, файловыми системами, внешними сервисами. Примеры: репозитории, Data Access Objects (DAO), API-клиенты для доступа к внешним системам. 🚩REST REST — это архитектурный стиль для разработки веб-сервисов. RESTful сервисы используют стандартные HTTP методы (GET, POST, PUT, DELETE и т.д.) для работы с ресурсами. С точки зрения трехслойной архитектуры: Презентационный слой: Вызовы REST API могут происходить с клиентской стороны (например, AJAX запросы из веб-интерфейса) или через клиентские приложения. Пример: фронтенд веб-приложения, который взаимодействует с REST API. Логический слой: REST API реализует бизнес-логику и выступает посредником между презентационным слоем и слоем данных. Пример: контроллеры и сервисы, обрабатывающие REST запросы и выполняющие соответствующую бизнес-логику. Слой данных: REST API может взаимодействовать с базой данных или другими источниками данных для получения и сохранения информации. Пример: методы в API, которые выполняют запросы к базе данных через репозитории или DAO. 🚩SWAP SWAP — это гипотетический или менее распространенный термин, часто интерпретируемый как упрощенный API для веб-приложений. Презентационный слой Клиентские приложения или пользовательские интерфейсы могут вызывать методы SWAP для получения или отправки данных.Пример: веб-страницы или мобильные приложения, обращающиеся к SWAP для выполнения операций. Логический слой: SWAP обрабатывает бизнес-логику аналогично REST API, предоставляя упрощенные конечные точки для взаимодействия с данными. Пример: сервисы, которые реализуют простые операции (CRUD) без сложной бизнес-логики. Слой данных: SWAP взаимодействует с базой данных или другими источниками данных для выполнения операций чтения/записи. Пример: методы SWAP, которые обращаются к базе данных через абстрактные уровни доступа к данным. Ставь 👍 и забирай 📚 Базу знаний
видео или голосовое, без подписи
🤔 Что делает 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` за кулисами? Выделение памяти в куче (для классов) или в стеке (для структур). Вызов конструктора класса или структуры. Возвращение ссылки на объект (для классов) или самого объекта (для структур). Ставь 👍 и забирай 📚 Базу знаний
видео или голосовое, без подписи
🤔 Как сейчас делается Singleton? В современном C# паттерн Singleton можно реализовать несколькими способами, каждый из которых имеет свои преимущества и предназначен для различных сценариев использования. Рассмотрим несколько распространенных подходов к реализации Singleton. 🟠Ленивый Singleton (Lazy Initialization) Ленивый Singleton инициализируется при первом обращении. Это обеспечивает отложенную инициализацию объекта и гарантирует потокобезопасность. public class Singleton { private static readonly Lazy<Singleton> lazyInstance = new Lazy<Singleton>(() => new Singleton()); public static Singleton Instance => lazyInstance.Value; private Singleton() { // Приватный конструктор } } 🟠Потокобезопасный Singleton (Thread-safe) Этот подход использует lock для обеспечения потокобезопасности при создании экземпляра. public class Singleton { private static Singleton instance; private static readonly object lockObj = new object(); private Singleton() { // Приватный конструктор } public static Singleton Instance { get { if (instance == null) { lock (lockObj) { if (instance == null) { instance = new Singleton(); } } } return instance; } } } Eager Initialization (Инициализация при загрузке) Экземпляр Singleton создается при загрузке класса. Это гарантирует потокобезопасность за счет особенностей инициализации статических переменных в .NET. public class Singleton { private static readonly Singleton instance = new Singleton(); public static Singleton Instance => instance; private Singleton() { // Приватный конструктор } } 🟠Static Constructor (Статический конструктор) Использование статического конструктора для инициализации Singleton. public class Singleton { private static readonly Singleton instance; static Singleton() { instance = new Singleton(); } public static Singleton Instance => instance; private Singleton() { // Приватный конструктор } } Singleton с внедрением зависимостей (Dependency Injection) В современных приложениях, особенно с использованием ASP.NET Core, Singleton часто регистрируется в контейнере внедрения зависимостей. public class SingletonService { public void DoWork() { // Выполнение работы } } // Регистрация в контейнере служб public void ConfigureServices(IServiceCollection services) { services.AddSingleton<SingletonService>(); } // Использование в контроллере public class MyController : ControllerBase { private readonly SingletonService _singletonService; public MyController(SingletonService singletonService) { _singletonService = singletonService; } public IActionResult Index() { _singletonService.DoWork(); return Ok(); } } Ставь 👍 и забирай 📚 Базу знаний
видео или голосовое, без подписи
🤔 Что из себя представляет абстракция? Это процесс выделения важных характеристик объекта и скрытия несущественных деталей. Она позволяет: 1. Создавать простые интерфейсы для сложных систем. 2. Сосредотачиваться на логике, а не на деталях реализации. 3. Обеспечивать полиморфизм и унифицированный подход к различным объектам. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
🤔 Что такое сборщик мусора? Сборщик мусора (Garbage Collector, GC) — это форма автоматического управления памятью. Он отслеживает каждый объект, выделенный в куче, и определяет, какие объекты более не доступны для приложения, а затем освобождает память, занимаемую этими объектами. Это ключевой компонент во многих современных языках программирования и средах выполнения, облегчая задачу управления памятью. 🚩Основные этапы работы 🟠Маркировка (Marking) Сборщик мусора периодически проходит через все объекты в куче, начиная с "корней" (объектов, непосредственно доступных в программе, например, через переменные в стеке вызовов и глобальные переменные). Он отмечает все объекты, до которых можно добраться напрямую или косвенно. 🟠Очистка (Sweeping) После маркировки доступных объектов, сборщик мусора удаляет все непомеченные объекты, освобождая ресурсы, которые они занимали. 🟠Компактификация (Compacting) Некоторые сборщики мусора перемещают оставшиеся объекты, чтобы уменьшить фрагментацию памяти и улучшить производительность работы с памятью. 🚩Ограничения 🟠Производительность Процесс сборки мусора может быть ресурсоёмким и может привести к заметным паузам в выполнении программы, особенно если куча большая. 🟠Непредсказуемость Точное время сборки мусора может быть непредсказуемым, что может создавать проблемы в приложениях с реальным временем. Ставь 👍 и забирай 📚 Базу знаний
🤔 Что такое исключения? Исключения в программировании — это механизмы обработки ошибок и необычных ситуаций, которые возникают во время выполнения программы. В C# и других языках программирования исключения позволяют отделить код обработки ошибок от основного кода программы, что упрощает его чтение и поддержку. 🚩Основные понятия 🟠Исключение (Exception) Событие, которое прерывает нормальный поток выполнения программы. 🟠Блок try Содержит код, который может вызвать исключение. 🟠Блок catch Содержит код, который выполняется, если возникает исключение. В catch блок можно передать параметр — экземпляр исключения, которое произошло. 🟠Блок finally Содержит код, который выполняется в любом случае, независимо от того, произошло исключение или нет. Обычно используется для освобождения ресурсов. 🟠Бросание исключения (throw) Механизм для явного вызова исключения. 🚩Пример использования Основные блоки try { // Код, который может вызвать исключение int divisor = 0; int result = 10 / divisor; } catch (DivideByZeroException ex) { // Обработка исключения Console.WriteLine("Деление на ноль невозможно."); } finally { // Код, который выполнится в любом случае Console.WriteLine("Блок finally выполнен."); } Создание и бросание собственного исключения public class InvalidAgeException : Exception { public InvalidAgeException(string message) : base(message) { } } public void SetAge(int age) { if (age < 0) { throw new InvalidAgeException("Возраст не может быть отрицательным."); } // Логика установки возраста } Ставь 👍 и забирай 📚 Базу знаний
видео или голосовое, без подписи
🤔 Какая есть классификация у кучи? В информатике и программировании куча (heap) может классифицироваться по нескольким критериям. Рассмотрим основные виды: 🟠По назначению: Куча памяти (Memory Heap) Используется для динамического выделения памяти в приложениях. В C# это управляется сборщиком мусора (GC - Garbage Collector). Примеры: объекты, созданные с помощью new, выделяются в управляемой куче. 🟠Структура данных «Куча» (Heap Data Structure) Это специальная бинарная структура данных, используемая в алгоритмах, например, в сортировке (Heap Sort) или в приоритетных очередях. Бывает максимальная куча (max-heap) и минимальная куча (min-heap). 🚩По типу управления памятью (для кучи памяти в языках программирования): 🟠Управляемая куча (Managed Heap) В C# и .NET память выделяется и освобождается автоматически с помощью GC. Разделяется на поколения (Generation 0, 1, 2), что оптимизирует работу сборщика мусора. 🟠Неуправляемая куча (Unmanaged Heap) Применяется в C/C++ и низкоуровневом коде, где управление памятью выполняется вручную (malloc/free, new/delete). В C# тоже можно работать с ней через Marshal или Unsafe код. 🟠По структуре данных (Heap Data Structure): 🟠Максимальная куча (Max Heap) Корневой узел содержит наибольшее значение, а дочерние узлы – меньшее. Используется в алгоритмах приоритетных очередей. 🟠Минимальная куча (Min Heap) Корневой узел содержит наименьшее значение, а дочерние узлы – большее. Применяется в алгоритме Дейкстры и других задачах. using System; using System.Collections.Generic; class Program { static void Main() { PriorityQueue<int, int> minHeap = new PriorityQueue<int, int>(); minHeap.Enqueue(5, 5); minHeap.Enqueue(3, 3); minHeap.Enqueue(8, 8); minHeap.Enqueue(1, 1); while (minHeap.Count > 0) { Console.WriteLine(minHeap.Dequeue()); // Выведет: 1, 3, 5, 8 } } } Ставь 👍 и забирай 📚 Базу знаний
🤔 Что такое 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)); } Ставь 👍 и забирай 📚 Базу знаний
🤔 Какие есть методы запросов жизненного цикла в asp.net Core? В ASP.NET Core жизненный цикл запроса проходит несколько этапов — от получения HTTP-запроса до отправки ответа. В этом процессе участвуют Middleware, контроллеры, фильтры и обработчики событий. 🚩Основные этапы жизненного цикла запроса Получение запроса (HttpContext создаётся) Обработка через Middleware (передача запроса вниз) Маршрутизация (Routing) — определение контроллера Фильтры (например, аутентификация) Вызов контроллера и метода (Action) Обратный проход через Middleware (формирование ответа) Отправка ответа клиенту 🚩Методы Middleware (Промежуточное ПО) Middleware — это основной механизм обработки запросов. Где регистрируются? → В Program.cs (в app.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(); Ставь 👍 и забирай 📚 Базу знаний
🤔 Что такое аутентификация? Когда человек вводит логин и пароль, система аутентифицирует его, проверяя, действительно ли это тот, за кого он себя выдаёт. 🚩Как работает аутентификация? Пользователь вводит данные (например, логин и пароль). Система проверяет их в базе данных. Если данные верны → доступ разрешён. Если данные неверны → отказ в доступе. 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 и микросервисах. Позволяет работать без сохранения сессий. Ставь 👍 и забирай 📚 Базу знаний
🤔 Как работает threadpool? ThreadPool (пул потоков) — это механизм управления потоками в .NET, который позволяет повторно использовать созданные потоки для выполнения задач, уменьшая накладные расходы на их создание и уничтожение. 🚩Зачем нужен ThreadPool? 🟠Создание потоков — дорогостоящая операция Каждый раз создавать новый поток — медленно и неэффективно. 🟠Пул потоков позволяет повторно использовать уже созданные потоки вместо их постоянного создания и удаления. 🟠Автоматическое управление количеством потоков в зависимости от нагрузки. 🟠Идеально подходит для небольших, кратковременных задач Обработки HTTP-запросов Выполнения задач в фоне Асинхронного выполнения операций 🚩Как работает ThreadPool? 🟠Когда вы отправляете задачу в ThreadPool он берет поток из пула и выполняет задачу. 🟠Если в пуле нет свободных потоков создается новый (но их количество ограничено). 🟠Когда задача выполнена, поток не уничтожается а возвращается в пул и может быть использован снова. 🟠ThreadPool сам регулирует количество потоков в зависимости от загрузки системы. 🚩Пример использования ThreadPool using System; using System.Threading; class Program { static void Main() { for (int i = 0; i < 5; i++) { ThreadPool.QueueUserWorkItem(DoWork, i); } Console.ReadLine(); // Ждём завершения потоков } static void DoWork(object? state) { Console.WriteLine($"Задача {state} выполняется в потоке {Thread.CurrentThread.ManagedThreadId}"); Thread.Sleep(1000); // Симуляция работы Console.WriteLine($"Задача {state} завершена"); } } 🚩Максимальное и минимальное количество потоков ThreadPool управляет количеством потоков сам, но их можно настраивать int minWorker, minIOC; ThreadPool.GetMinThreads(out minWorker, out minIOC); Console.WriteLine($"Мин. количество потоков: {minWorker}"); ThreadPool.SetMinThreads(4, 4); // Устанавливаем минимум потоков int maxWorker, maxIOC; ThreadPool.GetMaxThreads(out maxWorker, out maxIOC); Console.WriteLine($"Макс. количество потоков: {maxWorker}"); Ставь 👍 и забирай 📚 Базу знаний
🤔 Может ли в абстрактном классе не быть ни одного абстрактного метода? Да, может. Абстрактный класс не обязан содержать абстрактные методы. Он может использоваться как нельзя инстанцируемая базовая структура с частичной или полной реализацией, предназначенной для наследования. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
🤔 В чем суть 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 без наследования и изменения структуры классов. Ставь 👍 и забирай 📚 Базу знаний
🤔 Что такое метод Finalize? Метод Finalize() представляет собой специальный метод, который предназначен для выполнения финальной очистки ресурсов перед тем, как объект будет уничтожен сборщиком мусора. Это метод, который может быть определен в классе для очистки неуправляемых ресурсов, если класс не реализует интерфейс IDisposable. 🚩Особенности метода 🟠Автоматический вызов Сборщик мусора автоматически вызывает Finalize() на объекте, который не имеет других активных ссылок и который определяет финализатор. Это происходит непосредственно перед тем, как сборщик мусора освобождает память, занимаемую объектом. 🟠Определение в базовом классе `Object` Все объекты наследуют от базового класса Object, который предоставляет реализацию Finalize(). Однако в большинстве случаев Finalize() не имеет реализации и не делает ничего, пока не будет переопределен в производном классе. 🟠Замедление сборки мусора Наличие объектов с финализаторами может замедлить процесс сборки мусора, так как объекты, требующие финализации, должны быть обработаны дважды: сначала они помещаются в очередь финализации, а затем их память освобождается после выполнения Finalize(). class ResourceWrapper { // Конструктор public ResourceWrapper() { // Инициализация ресурсов } // Финализатор ~ResourceWrapper() { // Код очистки ресурсов } } Ставь 👍 и забирай 📚 Базу знаний