C# | Вопросы собесов
5.11K subscribers
35 photos
1 file
1.01K links
Download Telegram
🤔 Какие основные паттерны используются в back-end?

На back-end чаще всего используются:
- Repository — для доступа к данным.
- Unit of Work — управление транзакциями.
- Dependency Injection — разделение зависимостей и реализаций.
- CQRS — разделение команд и запросов.
- Mediator — упрощает взаимодействие между компонентами.
- Factory / Abstract Factory — динамическое создание объектов.
- Builder — создание сложных объектов шаг за шагом.
- Strategy — переключение алгоритмов без изменения клиентского кода.
- Adapter — интеграция сторонних библиотек и API.


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

HashSet — это коллекция уникальных элементов, основанная на хеш-таблице. Он:
- Обеспечивает быстрые вставку и поиск.
- Не допускает дубликатов.
- Не гарантирует порядок.
Используется, когда нужно отфильтровать повторения и обеспечить быстрый доступ.


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

Сравнение значений переменных может зависеть от типа данных, хранящихся в этих переменных, и от способа их сравнения.

🟠Примитивные типы (Value Types)
Для примитивных типов (например, int, float, char, bool) значение хранятся непосредственно в переменных, и их сравнение выполняется по значению.
int a = 5;
int b = 5;

bool areEqual = (a == b); // True


🟠Ссылочные типы (Reference Types)
Для ссылочных типов (например, классы, строки) переменные содержат ссылки на объекты в куче. Сравнение ссылочных типов по умолчанию выполняется по ссылке, а не по значению.
class Person
{
public string Name { get; set; }
}

Person person1 = new Person { Name = "Alice" };
Person person2 = new Person { Name = "Alice" };

bool areEqual = (person1 == person2); // False, потому что сравниваются ссылки


🟠Строки (Strings)
Строки являются ссылочными типами, но переопределяют операторы сравнения == и Equals для сравнения по значению.
string str1 = "Hello";
string str2 = "Hello";

bool areEqual = (str1 == str2); // True, строки сравниваются по значению


🟠Кастомные классы
Для кастомных классов можно переопределить методы Equals и GetHashCode, чтобы сравнивать объекты по значению.
class Person
{
public string Name { get; set; }

public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
return false;

Person other = (Person)obj;
return Name == other.Name;
}

public override int GetHashCode()
{
return Name.GetHashCode();
}
}

Person person1 = new Person { Name = "Alice" };
Person person2 = new Person { Name = "Alice" };

bool areEqual = person1.Equals(person2); // True


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

Нет, значимые типы (структуры) обычно хранятся в стеке, но если они являются частью объекта ссылочного типа, то хранятся в куче. Это зависит от контекста их использования.


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

Dispose и Finalize являются двумя механизмами для управления ресурсами, особенно теми, которые не управляются средой выполнения .NET, такими как файловые дескрипторы или соединения с базой данных. Они играют важную роль в освобождении ресурсов, но работают по-разному.

🚩Finalize

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

🚩Dispose

Является частью интерфейса IDisposable и предоставляет явный способ освобождения управляемых и неуправляемых ресурсов. Разработчики могут вызывать Dispose вручную или использовать конструкцию using, которая гарантирует вызов Dispose по завершении блока кода.

public class ResourceHolder : IDisposable
{
private bool disposed = false;

~ResourceHolder() // Финализатор
{
Dispose(false);
}

public void Dispose() // Метод Dispose из IDisposable
{
Dispose(true);
GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Освобождение управляемых ресурсов
}

// Освобождение неуправляемых ресурсов
disposed = true;
}
}
}


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

Проблемы: состояния гонки, deadlock, livelock, взаимные блокировки и неправильная синхронизация данных. Их избегают с помощью использования примитивов синхронизации (например, lock, Monitor, Mutex), разделения ответственности между потоками, атомарных операций и минимизации общего доступа к ресурсам.

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

- var — тип определяется на этапе компиляции. После компиляции он получает конкретный тип. Статическая типизация.
- dynamic — тип определяется во время выполнения. Ошибки типа могут проявиться только в рантайме.
var безопаснее, dynamic гибче, но требует осторожности.


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

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

🚩Абстрактный класс

Абстрактный класс — это класс, который не может быть создан напрямую (нельзя создать объект этого класса). Он может содержать как абстрактные методы (без реализации), так и методы с реализацией.
public abstract class Animal
{
public abstract void MakeSound(); // Абстрактный метод
public void Sleep() // Метод с реализацией
{
Console.WriteLine("Sleeping...");
}
}


Пример
public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Bark!");
}
}


Использование
Animal myDog = new Dog();
myDog.MakeSound(); // Вывод: Bark!
myDog.Sleep(); // Вывод: Sleeping...


🚩Интерфейс

Интерфейс — это контракт, который определяет только сигнатуры методов, свойств, событий и индексаторов. Реализацию этих членов должен предоставить класс, который реализует интерфейс.
public interface IMovable
{
void Move();
int Speed { get; set; }
}


Пример
public class Car : IMovable
{
public int Speed { get; set; }

public void Move()
{
Console.WriteLine($"Moving at speed: {Speed}");
}
}


Использование
IMovable myCar = new Car { Speed = 60 };
myCar.Move(); // Вывод: Moving at speed: 60


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from easyoffer
Черная пятница на easyoffer

Скидка 70% на PRO до 29 ноября.

👉 https://easyoffer.ru/
🤔 Что такое зацепление в коде?

Зацепление (coupling) — это мера зависимости одного модуля от другого.
- Сильное зацепление (tight coupling) — классы жёстко связаны, изменение одного требует изменения другого.
- Слабое зацепление (loose coupling) — классы слабо связаны через абстракции (например, интерфейсы), что повышает гибкость, масштабируемость и тестируемость.
Цель хорошего дизайна — добиться слабого зацепления и высокой связности внутри модуля.


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

Сборщик мусора (Garbage Collector, GC) — это форма автоматического управления памятью. Он отслеживает каждый объект, выделенный в куче, и определяет, какие объекты более не доступны для приложения, а затем освобождает память, занимаемую этими объектами. Это ключевой компонент во многих современных языках программирования и средах выполнения, облегчая задачу управления памятью.

🚩Основные этапы работы

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

🟠Очистка (Sweeping)
После маркировки доступных объектов, сборщик мусора удаляет все непомеченные объекты, освобождая ресурсы, которые они занимали.

🟠Компактификация (Compacting)
Некоторые сборщики мусора перемещают оставшиеся объекты, чтобы уменьшить фрагментацию памяти и улучшить производительность работы с памятью.

🚩Ограничения

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

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