C# | Вопросы собесов
前往频道在 Telegram
Сайт: https://easyoffer.ru/ Все каналы: t.me/+xGeAw6ckJ4liYzQy Контакт для рекламы: @sendme_ads
显示更多5 013
订阅者
无数据24 小时
+27 天
+2230 天
帖子存档
5 013
🤔 Что такое .NET Standard?
Это спецификация API, поддерживаемых различными реализациями платформы .NET, такими как .NET Framework, .NET Core и Xamarin.
1. Обеспечивает совместимость между этими реализациями, позволяя разрабатывать общий код.
2. Разработчики могут писать библиотеки, работающие на разных версиях и платформах .NET.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
5 013
🤔 Приведи пример паттерна строитель в С#
Паттерн "Строитель" (Builder) используется для пошагового создания сложных объектов. Он удобен, когда объект имеет много параметров и возможных конфигураций.
🚩Проблема без паттерна "Строитель"
Допустим, у нас есть класс
Car, и мы хотим создавать машины с разными конфигурациями:
public class Car
{
public string Engine { get; set; }
public int Wheels { get; set; }
public bool HasSunroof { get; set; }
public override string ToString()
{
return $"Car: Engine={Engine}, Wheels={Wheels}, Sunroof={HasSunroof}";
}
}
Создавать объект через конструкторы или инициализаторы становится неудобно, если у нас много параметров:
var car1 = new Car { Engine = "V8", Wheels = 4, HasSunroof = true };
var car2 = new Car { Engine = "V6", Wheels = 4, HasSunroof = false };
🚩Решение с использованием паттерна "Строитель"
Сделаем пошаговый процесс сборки объекта с помощью паттерна "Строитель".
Шаг 1: Создаём интерфейс строителя
public interface ICarBuilder
{
ICarBuilder SetEngine(string engine);
ICarBuilder SetWheels(int wheels);
ICarBuilder SetSunroof(bool hasSunroof);
Car Build();
}
Шаг 2: Реализуем конкретного строителя
public class CarBuilder : ICarBuilder
{
private Car _car = new Car(); // Временный объект
public ICarBuilder SetEngine(string engine)
{
_car.Engine = engine;
return this; // Возвращаем самого себя для цепочки вызовов
}
public ICarBuilder SetWheels(int wheels)
{
_car.Wheels = wheels;
return this;
}
public ICarBuilder SetSunroof(bool hasSunroof)
{
_car.HasSunroof = hasSunroof;
return this;
}
public Car Build()
{
return _car; // Возвращаем готовый объект
}
}
Шаг 3: Используем строителя
class Program
{
static void Main()
{
ICarBuilder builder = new CarBuilder();
Car sportsCar = builder
.SetEngine("V8")
.SetWheels(4)
.SetSunroof(true)
.Build();
Car economyCar = builder
.SetEngine("V4")
.SetWheels(4)
.SetSunroof(false)
.Build();
Console.WriteLine(sportsCar);
Console.WriteLine(economyCar);
}
}
Вывод в консоли
Car: Engine=V8, Wheels=4, Sunroof=True Car: Engine=V4, Wheels=4, Sunroof=FalseСтавь 👍 и забирай 📚 Базу знаний
5 013
Хотите разобраться в тестировании API на ASP.NET Core?
➡️ Присоединяйтесь к открытому уроку «Тестирование API в ASP.NET Core: Интеграция и Нагрузка» 5 августа в 20:00 МСК. На вебинаре мы:
- Разберем ключевые концепции интеграционного и нагрузочного тестирования.
- Научимся писать интеграционные тесты с популярными библиотеками.
- Освоим инструменты для нагрузочного тестирования и анализа результатов.
📗 Этот урок — отличная подготовка к курсу «C# ASP.NET Core разработчик», который стартует совсем скоро. Все участники вебинара получат скидку на обучение!
Записаться на вебинар → https://otus.pw/MXNg/
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
5 013
🤔 Как сделать миграцию методов?
Миграция методов подразумевает их перемещение или переработку между классами, что требует анализа текущей логики и всех мест, где методы используются. Следует обновить ссылки, провести рефакторинг кода и написать тесты для проверки функциональности после изменений. Это помогает минимизировать риски нарушения работы системы.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
5 013
🤔 Что из себя представляет библиотека dependency injectuion?
Dependency Injection (DI) — это паттерн проектирования, который помогает управлять зависимостями в приложении, делая код более гибким, тестируемым и поддерживаемым. Библиотека DI предоставляет механизмы для внедрения зависимостей автоматически, без явного создания экземпляров объектов в коде.
🚩Зачем нужна библиотека DI?
Без DI мы часто создаем объекты внутри классов вручную, что приводит к жесткой связности (tight coupling). Это делает код менее гибким и сложным в тестировании. DI помогает:
Разделить зависимости: объекты получают зависимости извне, а не создают их самостоятельно.
Облегчить тестирование: можно подставлять мок-объекты вместо реальных зависимостей.
Сделать код более гибким: легко подменять реализации зависимостей.
🚩Как работает DI?
В .NET Core и .NET 5+ встроена своя Microsoft.Extensions.DependencyInjection, но можно использовать сторонние библиотеки, такие как Autofac, Ninject, Unity.
Регистрация зависимостей
Внедрение зависимостей
Жизненный цикл зависимостей
🚩Пример DI в C# (.NET Core)
Создадим интерфейс и его реализацию
public interface IMessageService
{
void SendMessage(string message);
}
public class EmailService : IMessageService
{
public void SendMessage(string message)
{
Console.WriteLine($"Отправка Email: {message}");
}
}
Зарегистрируем зависимость в DI-контейнере
var serviceProvider = new ServiceCollection()
.AddSingleton<IMessageService, EmailService>()
.BuildServiceProvider();
Получим зависимость через DI
var messageService = serviceProvider.GetService<IMessageService>();
messageService.SendMessage("Привет, DI!");
Ставь 👍 и забирай 📚 Базу знаний5 013
🤔 В чём разница между списком и массивом?
1. Список (List): динамическая структура данных, которая может менять размер. Поддерживает методы для работы с элементами (добавление, удаление).
2. Массив: фиксированная структура данных, размер задаётся при создании. Более эффективен в использовании памяти, но менее гибок.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
5 013
🤔 Если мы используем 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
Ставь 👍 и забирай 📚 Базу знаний5 013
🤔 Что такое инкапсуляция?
Инкапсуляция в объектно-ориентированном программировании — это механизм упаковки данных (переменных) и кода, работающего с данными (методов), в один объект и ограничение доступа к некоторым компонентам объекта, что способствует безопасности и упрощению интерфейса.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
5 013
🤔 Какие бывают типы данных?
В C# существует множество различных типов данных, которые можно разделить на две основные категории: значимые типы (value types) и ссылочные типы (reference types). Рассмотрим каждую из этих категорий и их подтипы.
🚩Значимые типы (Value Types)
Значимые типы хранят данные непосредственно в своей памяти. Они обычно располагаются в стеке и имеют фиксированный размер. К значимым типам относятся:
🟠Простые типы (Simple Types)
Числовые типы
Целочисленные типы:
byte (8 бит)
sbyte (8 бит)
short (16 бит)
ushort (16 бит)
int (32 бита)
uint (32 бита)
long (64 бита)
ulong (64 бита)
Вещественные типы:
float (32 бита)
double (64 бита)
Десятичный тип:
decimal (128 бит)
Логический тип
bool (1 бит, значения true или false)
Символьный тип
char (16 бит, символы в формате Unicode)
🟠Структуры (Structs)
Пользовательские типы, которые могут содержать поля, свойства и методы. Пример: struct Point { public int X; public int Y; }
🟠Перечисления (Enums)
Специальные типы, представляющие набор именованных констант. Пример: enum Days { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday }
🟠Nullable Types
Типы, которые могут принимать значение null. Пример: int?, double?
🚩Ссылочные типы (Reference Types)
🟠Классы (Classes)
Основные объекты в C#, могут содержать поля, свойства, методы и события. Пример: class Person { public string Name; public int Age; }
🟠Интерфейсы (Interfaces)
Определяют контракт, который должны реализовать классы. Пример: interface IMovable { void Move(); }
🟠Массивы (Arrays)
Коллекции однотипных элементов. Пример: int[] numbers = new int[5];
🟠Делегаты (Delegates)
Типы, которые представляют собой ссылки на методы. Пример: delegate void Process(int value);
🟠Строки (Strings)
Непосредственно представляют собой последовательность символов. Пример: string message = "Hello, World!";
🟠Записи (Records)
Новый тип в C# 9.0, предназначенный для неизменяемых объектов. Пример: record Person(string Name, int Age);
🚩Примеры и использование
Значимые типы
int a = 5;
float b = 3.14f;
bool isTrue = true;
char letter = 'A';
Ссылочные типы
string message = "Hello, World!";
Person person = new Person { Name = "Alice", Age = 30 };
int[] numbers = new int[] { 1, 2, 3, 4, 5 };
Ставь 👍 и забирай 📚 Базу знаний5 013
🤔 Что такое ООП?
ООП (Объектно-Ориентированное Программирование) — это парадигма программирования, основанная на концепции объектов, которые объединяют данные и методы для их обработки. Основные принципы ООП включают инкапсуляцию, наследование, полиморфизм и абстракцию. ООП позволяет моделировать реальный мир с помощью классов и объектов, улучшая структуру и повторное использование кода. В C# все программы строятся на основе классов, что делает его строго объектно-ориентированным языком.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
5 013
🤔 Что такое 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));
}
Ставь 👍 и забирай 📚 Базу знаний5 013
🤔 Что такое DTO?
DTO (Data Transfer Object):
- Это простой класс, предназначенный только для передачи данных между слоями (например, между API и сервисом).
- Не содержит логики, только поля и свойства.
- Часто используется:
- при сериализации;
- в REST API;
- для защиты бизнес-модели от утечек наружу.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
5 013
🤔 В чем разница между FirstOfDefault и SingleOfDefault?
Методы
FirstOrDefault и SingleOrDefault в LINQ используются для извлечения элементов из коллекции, но их логика работы отличается. Давайте разберем их подробно, с примерами.
🚩FirstOrDefault
FirstOrDefault возвращает первый элемент коллекции, который удовлетворяет условию (если условие указано), или первый элемент вообще, если условие отсутствует. Если в коллекции нет элементов, метод возвращает значение по умолчанию для типа (например, null для ссылочных типов или 0 для чисел).
Когда вас интересует первый элемент коллекции, но коллекция может быть пустой.
Когда вам неважно, есть ли другие элементы, соответствующие условию.
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
// Возьмем первый элемент, который больше 3
int result = numbers.FirstOrDefault(n => n > 3); // result = 4
// Если условие не выполняется
int result2 = numbers.FirstOrDefault(n => n > 10); // result2 = 0 (default для int)
// Если коллекция пустая
List<int> emptyList = new List<int>();
int result3 = emptyList.FirstOrDefault(); // result3 = 0
🚩SingleOrDefault
SingleOrDefault возвращает единственный элемент из коллекции, который удовлетворяет условию. Если такого элемента нет, метод возвращает значение по умолчанию. Однако если в коллекции есть более одного элемента, удовлетворяющего условию, будет выброшено исключение (InvalidOperationException).
Когда вы ожидаете, что в коллекции будет ровно один элемент, соответствующий условию.
Когда наличие нескольких подходящих элементов является ошибкой и вы хотите это обработать.
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
// Возьмем единственный элемент, равный 3
int result = numbers.SingleOrDefault(n => n == 3); // result = 3
// Если элемента, соответствующего условию, нет
int result2 = numbers.SingleOrDefault(n => n > 10); // result2 = 0
// Если элементов больше одного, возникает исключение
List<int> duplicateNumbers = new List<int> { 1, 2, 3, 3, 4 };
try
{
int result3 = duplicateNumbers.SingleOrDefault(n => n > 2);
}
catch (InvalidOperationException ex)
{
Console.WriteLine(ex.Message); // Ошибка: последовательность содержит несколько элементов
}
Ставь 👍 и забирай 📚 Базу знаний5 013
🤔 Какие есть фазы очистки ресурсов?
Управление ресурсами в .NET делится на несколько этапов:
1. Finalize (финализатор):
- Позволяет объекту реагировать на удаление.
- Вызывается сборщиком мусора.
- Используется редко, потому что непредсказуем по времени.
2. Dispose:
- Ручной способ освободить управляемые и неуправляемые ресурсы.
- Используется через IDisposable.
- Можно вызывать через конструкцию try-with-resources (using).
3. GC.Collect():
- Принудительно запускает сборку мусора.
- Не рекомендуется использовать без нужды.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
5 013
🤔 Что в себе может хранить делегат?
Делегат (
delegate) — это указатель на метод(ы). Он может хранить:
1. Ссылку на один метод (одиночный делегат)
2. Ссылки на несколько методов (групповой делегат / multicast)
3. Анонимные методы и лямбда-выражения
🚩Делегат хранит ссылку на метод
Делегаты позволяют вызвать метод, даже если его имя заранее неизвестно.
Пример с одиночным делегатом
public delegate void MyDelegate(string message); // Объявляем делегат
public class Program
{
public static void ShowMessage(string msg) => Console.WriteLine($"Сообщение: {msg}");
public static void Main()
{
MyDelegate del = ShowMessage; // Делегат хранит ссылку на метод
del("Привет, делегаты!"); // Вызывает ShowMessage
}
}
🚩Делегат может хранить несколько методов (Multicast)
Делегаты можно связывать с несколькими методами с помощью +=. Пример группового делегата
public delegate void MyDelegate(string message);
public class Program
{
public static void Method1(string msg) => Console.WriteLine($"Метод 1: {msg}");
public static void Method2(string msg) => Console.WriteLine($"Метод 2: {msg}");
public static void Main()
{
MyDelegate del = Method1;
del += Method2; // Добавляем второй метод
del("Привет!");
// Выведет:
// Метод 1: Привет!
// Метод 2: Привет!
}
}
🚩Делегат может хранить анонимные методы и лямбды
Делегаты могут хранить "встроенные" методы (без отдельного определения).
Пример с анонимным методом
MyDelegate del = delegate (string msg)
{
Console.WriteLine($"Анонимный метод: {msg}");
};
del("Привет!");
Пример с лямбда-выражением
MyDelegate del = msg => Console.WriteLine($"Лямбда: {msg}");
del("Привет!");
Ставь 👍 и забирай 📚 Базу знаний5 013
🤔 Что такое RESTful?
RESTful = соответствующий принципам REST.
Это не технология, а стиль построения API. RESTful API — это API, которое:
- Строится вокруг ресурсов.
- Использует HTTP-методы по назначению.
- Придерживается stateless взаимодействия.
- Предоставляет понятную структуру URL.
- Использует стандартизированные коды ответа.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
5 013
🤔 Как в кучах разделяются объекты?
В .NET среде управления памятью, объекты размещаются в куче (heap), и управление памятью осуществляется сборщиком мусора (Garbage Collector, GC). Куча разделена на несколько поколений для оптимизации производительности управления памятью.
🚩Поколения кучи
Куча в .NET разделена на три поколения: Generation 0, Generation 1 и Generation 2. Это разделение позволяет эффективно управлять памятью, минимизируя частоту сборок мусора и оптимизируя их выполнение.
🟠Generation 0
Содержит новосозданные объекты. Сборка мусора для этого поколения происходит чаще, так как большинство объектов "умирает" быстро. Наименьший размер среди всех поколений.
🟠Generation 1
Промежуточное поколение, используемое для объектов, которые пережили хотя бы одну сборку мусора Generation 0. Содержит объекты с более длительным временем жизни, чем объекты в Generation 0.
🟠Generation 2
Содержит объекты с самым длительным временем жизни. Наибольший размер среди всех поколений. Сборка мусора для этого поколения происходит реже всего.
🚩Large Object Heap (LOH)
LOH используется для размещения крупных объектов (размером 85,000 байт и более). Объекты в LOH не перемещаются при сборке мусора, что уменьшает фрагментацию памяти. Сборка мусора для LOH происходит одновременно со сборкой Generation 2.
🚩Как разделяются объекты
🟠Размещение объектов
При создании объекта он сначала размещается в Generation 0. Если объект переживает сборку мусора в Generation 0, он перемещается в Generation 1. Если объект переживает сборку мусора в Generation 1, он перемещается в Generation 2.
🟠Сборка мусора
Generation 0: Быстрая и частая сборка. Цель - освободить память от краткоживущих объектов.
Generation 1: Реже, чем Generation 0. Служит промежуточной зоной.
Generation 2: Самая редкая и длительная сборка. Обрабатывает долгоживущие объекты.
Large Object Heap (LOH): Сборка мусора проводится вместе с Generation 2.
public class Program
{
public static void Main()
{
// Создание объектов в Generation 0
for (int i = 0; i < 1000; i++)
{
var obj = new object();
}
// Создание большого объекта (размещается в LOH)
byte[] largeArray = new byte[100000];
// Принудительный вызов сборщика мусора
GC.Collect();
// Проверка поколения объекта
Console.WriteLine(GC.GetGeneration(largeArray)); // Скорее всего, 2
}
}
Ставь 👍 и забирай 📚 Базу знаний5 013
В Битрикс24 теперь можно сделать сайт за 30 секунд
Серьёзно. Пишешь, что нужно, и AI сам всё собирает: тексты, картинки, оформление.
✨Никакой магии, просто умный помощник.
Попробуйте — закайфуете от скорости!
Начать
#реклама 16+
sites-24.bitrix24.ru
О рекламодателе
5 013
🤔 Зачем нужен INotifyPropertyChanged интерфейс?
Он используется для уведомления UI о том, что свойство изменилось.
В MVVM паттерне это основа двусторонней привязки данных, без него UI не узнает, что нужно обновить отображение.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
5 013
🤔 Пример выполнения кода, когда возвращается объект интерфейса Iqueryable?
IQueryable<T> — это интерфейс, который используется для отложенного выполнения запросов (deferred execution). Он позволяет строить SQL-запросы к базе данных или манипулировать данными в памяти, но сам запрос выполняется только в момент его итерации (ToList(), FirstOrDefault(), Count(), и т. д.).
🚩Пример работы с `IQueryable<T>` на Entity Framework Core
Предположим, у нас есть сущность Product и контекст базы данных AppDbContext
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
public class AppDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("YourConnectionString");
}
}
Теперь создадим репозиторий, который возвращает IQueryable<Product>
public class ProductRepository
{
private readonly AppDbContext _context;
public ProductRepository(AppDbContext context)
{
_context = context;
}
public IQueryable<Product> GetProducts()
{
return _context.Products.Where(p => p.Price > 100);
// Запрос не выполняется здесь! Только формируется
}
}
🚩Вызов метода и выполнение запроса
Запрос к базе данных выполнится только при материализации (ToList(), FirstOrDefault(), Count(), и т. д.).
var repository = new ProductRepository(new AppDbContext());
// Создаём IQueryable-запрос
IQueryable<Product> query = repository.GetProducts();
// Добавляем дополнительное условие (запрос еще НЕ выполнен)
query = query.OrderBy(p => p.Name);
// Теперь выполняем запрос к БД
List<Product> products = query.ToList(); // SQL-запрос отправляется в базу
Ставь 👍 и забирай 📚 Базу знаний