C# | Вопросы собесов
5.09K subscribers
34 photos
1 file
978 links
Download Telegram
📌 Как сейчас делается Singleton?

💬 Спрашивают в 11% собеседований

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

1️⃣ Ленивый 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()
{
// Приватный конструктор
}
}


Lazy<T>: Использование класса Lazy<T> позволяет легко и безопасно реализовать отложенную инициализацию.

2️⃣ Потокобезопасный 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;
}
}
}


Double-checked locking: Этот метод минимизирует накладные расходы, связанные с использованием lock, проверяя instance дважды.

3️⃣ Eager Initialization (Инициализация при загрузке)

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

Пример:
public class Singleton
{
private static readonly Singleton instance = new Singleton();

public static Singleton Instance => instance;

private Singleton()
{
// Приватный конструктор
}
}


Простота: Этот метод прост и эффективен, но не поддерживает отложенную инициализацию.

4️⃣ Static Constructor (Статический конструктор)

Использование статического конструктора для инициализации Singleton.

Пример:
public class Singleton
{
private static readonly Singleton instance;

static Singleton()
{
instance = new Singleton();
}

public static Singleton Instance => instance;

private Singleton()
{
// Приватный конструктор
}
}


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

5️⃣ 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();
}
}


🤔 Краткий ответ

В C# паттерн Singleton реализуется с использованием различных подходов: ленивой инициализации (с Lazy<T>), потокобезопасного двойного блокирования, инициализации при загрузке класса и статического конструктора. В современных приложениях также используется внедрение зависимостей (DI), особенно в ASP.NET Core, для обеспечения единственного экземпляра.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5👍2
🤔 Что такое исключения (exceptions) и как они обрабатываются в C#?
Anonymous Quiz
99%
Блоками try, catch, finally.
1%
Методами include, require.
1%
Операторами check, uncheck.
0%
Командами start, end.
1
📌 Способы расширить поведение классов в C# на практике?

💬 Спрашивают в 11% собеседований

🤔 Способы расширения поведения классов в C#

1️⃣ Наследование: Создание подклассов, которые наследуют и переопределяют методы базового класса.
   public class BaseClass
{
public virtual void DoWork() { /* базовое поведение */ }
}

public class DerivedClass : BaseClass
{
public override void DoWork() { /* расширенное поведение */ }
}


2️⃣ Интерфейсы: Определение интерфейсов и их реализация в классах.
   public interface IWork
{
void DoWork();
}

public class MyClass : IWork
{
public void DoWork() { /* реализация интерфейса */ }
}


3️⃣ Декоратор: Оборачивание класса в другой класс для добавления поведения.
   public class BaseClass
{
public virtual void DoWork() { /* базовое поведение */ }
}

public class Decorator : BaseClass
{
private BaseClass _base;
public Decorator(BaseClass baseClass) { _base = baseClass; }
public override void DoWork()
{
_base.DoWork();
// Добавленное поведение
}
}


4️⃣ Адаптер: Преобразование интерфейса одного класса в интерфейс другого.
   public interface ITarget
{
void Request();
}

public class Adaptee
{
public void SpecificRequest() { /* специальное поведение */ }
}

public class Adapter : ITarget
{
private Adaptee _adaptee = new Adaptee();
public void Request() { _adaptee.SpecificRequest(); }
}


5️⃣ Расширяющие методы: Добавление методов к существующим типам без изменения их кода.
   public static class Extensions
{
public static void NewMethod(this ExistingClass obj)
{
// Добавленное поведение
}
}


🤔 Краткий ответ

Поведение классов в C# можно расширить через наследование, интерфейсы, паттерн декоратор, адаптер и расширяющие методы.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Please open Telegram to view this post
VIEW IN TELEGRAM
👍52🔥1
📌 Можно ли взять любой метод и поменять его поведение в классе наследнике?

💬 Спрашивают в 11% собеседований

В C# вы можете изменить поведение методов в классе-наследнике при соблюдении определенных условий. Рассмотрим основные способы изменения поведения методов в наследуемых классах.

🤔 Переопределение виртуальных методов

Если метод базового класса объявлен с ключевым словом virtual, его можно переопределить в классе-наследнике с использованием ключевого слова override.

🤔 Пример:
public class BaseClass
{
public virtual void DoWork()
{
Console.WriteLine("BaseClass DoWork");
}
}

public class DerivedClass : BaseClass
{
public override void DoWork()
{
Console.WriteLine("DerivedClass DoWork");
}
}

class Program
{
static void Main()
{
BaseClass obj = new DerivedClass();
obj.DoWork(); // Выведет: "DerivedClass DoWork"
}
}


🤔 Сокрытие методов

Если метод базового класса не объявлен с ключевым словом virtual, вы можете скрыть его в классе-наследнике с использованием ключевого слова new. Однако, это не является переопределением в строгом смысле, и поведение метода будет зависеть от типа ссылки на объект.

🤔 Пример:
public class BaseClass
{
public void DoWork()
{
Console.WriteLine("BaseClass DoWork");
}
}

public class DerivedClass : BaseClass
{
public new void DoWork()
{
Console.WriteLine("DerivedClass DoWork");
}
}

class Program
{
static void Main()
{
BaseClass objBase = new BaseClass();
objBase.DoWork(); // Выведет: "BaseClass DoWork"

DerivedClass objDerived = new DerivedClass();
objDerived.DoWork(); // Выведет: "DerivedClass DoWork"

BaseClass objPolymorphic = new DerivedClass();
objPolymorphic.DoWork(); // Выведет: "BaseClass DoWork"
}
}


🤔 Интерфейсы

Вы можете изменить или дополнить поведение, реализуя интерфейсы в классе-наследнике.

🤔 Пример:
public interface IWork
{
void DoWork();
}

public class BaseClass : IWork
{
public virtual void DoWork()
{
Console.WriteLine("BaseClass DoWork");
}
}

public class DerivedClass : BaseClass
{
public override void DoWork()
{
Console.WriteLine("DerivedClass DoWork");
}
}

class Program
{
static void Main()
{
IWork obj = new DerivedClass();
obj.DoWork(); // Выведет: "DerivedClass DoWork"
}
}


🤔 Краткий ответ

В C# вы можете изменить поведение методов в классе-наследнике, если метод базового класса объявлен как virtual. В этом случае вы можете переопределить его с использованием override. Для методов, не объявленных как virtual, можно использовать сокрытие (new), но это не даст полиморфного поведения.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍42
🤔 Какие существуют уровни доступа к членам класса в C#?
Anonymous Quiz
99%
public, private, protected, internal, protected internal.
0%
open, closed, abstract, final.
1%
internal, external, global, local.
0%
static, dynamic, final, transient.
1
📌 Можешь ли объяснить концепцию наследования в ООП?

💬 Спрашивают в 11% собеседований

Наследование — одна из ключевых концепций объектно-ориентированного программирования (ООП). Оно позволяет создавать новые классы на основе уже существующих, используя их свойства и методы, и при этом добавлять новые или изменять существующие.

🤔 Основные концепции наследования

1️⃣ Базовый класс (родительский класс, суперкласс): Класс, от которого наследуются другие классы.

2️⃣ Производный класс (дочерний класс, подкласс): Класс, который наследует свойства и методы базового класса.

🤔 Преимущества наследования

1️⃣ Повторное использование кода: Производный класс может использовать уже существующий код базового класса, что уменьшает дублирование кода.

2️⃣ Расширяемость: Производный класс может добавлять новые свойства и методы или переопределять существующие для расширения или изменения поведения.

3️⃣ Поддержка полиморфизма: Позволяет использовать один интерфейс для работы с объектами разных типов.

🤔 Пример наследования в C#

🤔 Базовый класс
public class Animal
{
public string Name { get; set; }

public void Eat()
{
Console.WriteLine("Eating...");
}

public virtual void MakeSound()
{
Console.WriteLine("Some generic animal sound");
}
}


🤔 Производный класс
public class Dog : Animal
{
public void Bark()
{
Console.WriteLine("Woof!");
}

public override void MakeSound()
{
Console.WriteLine("Bark");
}
}


🤔 Использование классов
class Program
{
static void Main()
{
Dog myDog = new Dog();
myDog.Name = "Buddy";
myDog.Eat(); // Наследованный метод
myDog.Bark(); // Метод производного класса
myDog.MakeSound(); // Переопределенный метод
}
}


🤔 Объяснение примера

1️⃣ Базовый класс `Animal`:

Имеет свойство Name и метод Eat.

Метод MakeSound объявлен как virtual, что позволяет его переопределить в производных классах.

2️⃣ Производный класс `Dog`:

Наследует свойства и методы базового класса Animal.

Добавляет новый метод Bark.

Переопределяет метод MakeSound с использованием ключевого слова override.

3️⃣ Создание экземпляра `Dog`:

Экземпляр класса Dog может использовать как унаследованные методы (Eat), так и методы, определенные в классе Dog (Bark).

Переопределенный метод MakeSound заменяет версию из базового класса Animal.

🤔 Полиморфизм

Наследование позволяет реализовать полиморфизм, который позволяет обрабатывать объекты производных классов через ссылки на базовый класс.

🤔 Пример полиморфизма
public class Cat : Animal
{
public override void MakeSound()
{
Console.WriteLine("Meow");
}
}

class Program
{
static void Main()
{
Animal myDog = new Dog();
Animal myCat = new Cat();

myDog.MakeSound(); // Выведет: Bark
myCat.MakeSound(); // Выведет: Meow
}
}


🤔 Краткий ответ

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

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
📌 В чем разница между переменными const, readonly и static?

💬 Спрашивают в 11% собеседований

В C# const, readonly и static используются для разных целей и имеют разные характеристики. Давайте рассмотрим различия между ними.

🤔 `const`

Описание: Поле, объявленное как const, является константой и должно быть инициализировано во время объявления. Значение const поля не может быть изменено после компиляции.

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

Тип данных: const поддерживает только примитивные типы данных, строки и enum.

🤔 Пример:
public class MyClass
{
public const int MyConst = 10;
}


🤔 `readonly`

Описание: Поле, объявленное как readonly, может быть инициализировано либо во время объявления, либо в конструкторе. Значение readonly поля может быть изменено только в конструкторе и не может быть изменено после этого.

Область применения: readonly поля используются для значений, которые должны быть неизменными после инициализации объекта, но могут различаться между экземплярами класса.

Тип данных: readonly поддерживает любые типы данных.

🤔 Пример:
public class MyClass
{
public readonly int MyReadonly;

public MyClass(int value)
{
MyReadonly = value;
}
}


🤔 `static`

Описание: Поле, объявленное как static, принадлежит классу, а не конкретному экземпляру. Оно является общим для всех экземпляров класса и хранится в одной области памяти.

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

Тип данных: static поддерживает любые типы данных.

🤔 Пример:
public class MyClass
{
public static int MyStatic;

static MyClass()
{
MyStatic = 10;
}
}


🤔 Краткое сравнение

| Характеристика | const | readonly | static |
|--------------------|----------------------------------|------------------------------------|------------------------------------|
| Инициализация | Во время объявления | Во время объявления или в конструкторе | В статическом конструкторе или во время объявления |
| Изменение | Нельзя изменять после компиляции | Можно изменять только в конструкторе | Можно изменять в любом месте кода |
| Область действия | Локальная для класса или метода | Локальная для экземпляра | Общая для всех экземпляров |
| Тип данных | Примитивные, строки, enum | Любые типы данных | Любые типы данных |

🤔 Краткий ответ

const: Неизменяемая константа, инициализируется при объявлении, не может быть изменена.

readonly: Неизменяемое поле после инициализации в конструкторе, поддерживает любые типы данных.

static: Поле, общее для всех экземпляров класса, может быть изменено в любое время.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
📌 Чем .NET CORE отличается от .net framework?

💬 Спрашивают в 11% собеседований

.NET Core и .NET Framework — это две различные реализации платформы .NET, и между ними есть несколько ключевых различий:

1️⃣ Кросс-платформенность

.NET Core: Разработан как кросс-платформенная платформа, поддерживающая Windows, macOS и Linux. Это позволяет разрабатывать и развертывать приложения на различных операционных системах.

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

2️⃣ Производительность и масштабируемость

.NET Core: Оптимизирован для высокой производительности и масштабируемости. Часто используется для разработки высоконагруженных и облачных приложений.

.NET Framework: Производительность также хороша, но в некоторых сценариях .NET Core показывает лучшие результаты благодаря более новым оптимизациям.

3️⃣ Модель развертывания

.NET Core: Поддерживает автономное развертывание (self-contained deployment), где все зависимости, включая .NET Core runtime, включаются в пакет приложения. Также поддерживает развертывание с зависимостью от общесистемного runtime (framework-dependent deployment).

.NET Framework: Приложения зависят от установленной версии .NET Framework на системе, что может вызвать проблемы совместимости.

4️⃣ Обновления и поддержка

.NET Core: Регулярно обновляется, с новыми версиями, выпущенными каждые несколько лет. Это включает в себя как новые функции, так и улучшения производительности.

.NET Framework: Получает обновления, но развитие замедлилось в пользу .NET Core и будущей унифицированной платформы .NET (начиная с .NET 5).

5️⃣ Архитектура и библиотеки

.NET Core: Более модульная архитектура, с поддержкой NuGet для управления зависимостями. Поддерживает библиотеку .NET Standard, что облегчает создание кода, работающего на разных реализациях .NET.

.NET Framework: Менее модульная, с монолитной установкой библиотек и зависимостей.

6️⃣ Инструменты и среда разработки

.NET Core: Поддерживает новые инструменты и среды разработки, такие как Visual Studio Code и командная строка. Также интегрирован с DevOps-инструментами и контейнерами, такими как Docker.

.NET Framework: Основной инструмент разработки — Visual Studio. Поддержка DevOps и контейнеров возможна, но требует дополнительных усилий.

7️⃣ Сценарии использования

.NET Core: Подходит для разработки новых облачных приложений, микросервисов, и кросс-платформенных приложений.

.NET Framework: Лучше подходит для существующих приложений, которые сильно зависят от Windows, таких как приложения Windows Forms или WPF.

🤔 Пример

🤔 .NET Core
// Пример консольного приложения на .NET Core
using System;

class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, .NET Core!");
}
}


🤔 .NET Framework
// Пример консольного приложения на .NET Framework
using System;

namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, .NET Framework!");
}
}
}


🤔 Краткий ответ

.NET Core: Кросс-платформенная, высокопроизводительная, модульная, с частыми обновлениями и поддержкой современных инструментов.

.NET Framework: Только для Windows, менее частые обновления, монолитная структура, лучше подходит для старых приложений, зависящих от Windows.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍131
📌 Объясните принцип работы паттерна медиатор?

💬 Спрашивают в 11% собеседований

Паттерн Медиатор (Mediator) относится к поведенческим паттернам проектирования и предназначен для уменьшения зависимости между объектами, что облегчает их взаимодействие и повышает их повторное использование. Медиатор инкапсулирует способ взаимодействия множества объектов, предотвращая их прямое взаимодействие и вместо этого направляя взаимодействие через центральный объект — медиатор.

🤔 Принцип работы

1️⃣ Централизованное управление взаимодействиями: Медиатор управляет взаимодействиями между объектами, выступая в роли центрального узла. Объекты не взаимодействуют напрямую друг с другом, вместо этого они взаимодействуют через медиатор.

2️⃣ Ослабление связей: Объекты становятся менее зависимыми друг от друга, что облегчает их изменение, замену или повторное использование.

3️⃣ Снижение сложности: Медиатор снижает сложность системы, упрощая взаимодействие между множеством объектов.

🤔 Компоненты паттерна Медиатор

1️⃣ Медиатор (Mediator): Интерфейс, который определяет методы для взаимодействия с коллегами.

2️⃣ Конкретный Медиатор (Concrete Mediator): Реализация интерфейса медиатора. Хранит ссылки на коллег и координирует их взаимодействие.

3️⃣ Коллеги (Colleagues): Классы, которые взаимодействуют друг с другом через медиатор. Каждый коллега имеет ссылку на медиатор и использует его для взаимодействия с другими коллегами.

🤔 Пример реализации

Рассмотрим пример чата, где различные компоненты (пользователи) общаются друг с другом через медиатор (чат-комнату).

🤔 Интерфейс Медиатор
public interface IChatRoomMediator
{
void ShowMessage(User user, string message);
}


🤔 Конкретный Медиатор
public class ChatRoom : IChatRoomMediator
{
public void ShowMessage(User user, string message)
{
string time = DateTime.Now.ToString("HH:mm");
string sender = user.Name;

Console.WriteLine($"{time} [{sender}]: {message}");
}
}


🤔 Коллега
public class User
{
private IChatRoomMediator _chatRoom;
public string Name { get; private set; }

public User(IChatRoomMediator chatRoom, string name)
{
_chatRoom = chatRoom;
Name = name;
}

public void Send(string message)
{
_chatRoom.ShowMessage(this, message);
}
}


🤔 Использование
class Program
{
static void Main(string[] args)
{
IChatRoomMediator chatRoom = new ChatRoom();

User user1 = new User(chatRoom, "Alice");
User user2 = new User(chatRoom, "Bob");

user1.Send("Hello, Bob!");
user2.Send("Hi, Alice!");
}
}


🤔 Объяснение

1️⃣ Медиатор (IChatRoomMediator): Интерфейс для взаимодействия с чат-комнатой.

2️⃣ Конкретный Медиатор (ChatRoom): Реализация интерфейса медиатора. Координирует взаимодействие между пользователями.

3️⃣ Коллега (User): Пользователь, который взаимодействует с другими пользователями через чат-комнату.

4️⃣ Использование: Пользователи отправляют сообщения через медиатор, который отвечает за отображение сообщений.

🤔 Краткий ответ

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

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥6
📌 Каковы преимущества и недостатки использования контейнеров, таких как Docker в .NET приожениях?

💬 Спрашивают в 11% собеседований

Использование контейнеров, таких как Docker, в .NET приложениях имеет множество преимуществ, но также и некоторые недостатки. Вот основные из них:

🤔 Преимущества

1️⃣ Портативность:

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

Пример: Docker-образ, созданный на локальной машине разработчика, может быть запущен на сервере производства без изменений.

2️⃣ Изолированность:

Контейнеры изолируют приложения и их зависимости, предотвращая конфликты между различными версиями библиотек и инструментов.

Пример: Разные версии .NET Core могут сосуществовать на одной машине в разных контейнерах.

3️⃣ Легкость масштабирования:

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

Пример: В Kubernetes можно легко добавить новые поды с контейнерами, чтобы справиться с повышенной нагрузкой.

4️⃣ Быстрое развертывание и запуск:

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

Пример: Docker-контейнер может быть запущен за несколько секунд, тогда как виртуальная машина может загружаться несколько минут.

5️⃣ Консистентность среды:

Контейнеры обеспечивают консистентность среды между разработкой, тестированием и продакшн-окружением.

Пример: Одинаковая версия .NET Runtime и конфигурации могут быть гарантированы во всех средах.

6️⃣ Упрощенная CI/CD:

Контейнеры интегрируются с инструментами CI/CD, что упрощает автоматизацию сборки, тестирования и развертывания.

Пример: Jenkins или GitHub Actions могут использовать Docker для создания и тестирования приложений в изолированных средах.

🤔 Недостатки

1️⃣ Изучение и сложность:

Понимание и настройка контейнеров и связанных инструментов требует времени и навыков.

Пример: Изучение Docker, Docker Compose и Kubernetes может занять значительное время для команды.

2️⃣ Производительность:

Хотя контейнеры легче, чем виртуальные машины, они все равно добавляют некоторую накладную на производительность.

Пример: Контейнеры могут использовать больше ресурсов, чем напрямую запущенные на хосте процессы, особенно при интенсивных I/O операциях.

3️⃣ Безопасность:

Контейнеры изолируют процессы, но изоляция не так сильна, как у виртуальных машин. Ошибки конфигурации могут привести к проблемам безопасности.

Пример: Уязвимость в Docker или неправильная конфигурация сетевых правил могут привести к компрометации контейнера.

4️⃣ Ограничения хост-системы:

Контейнеры зависят от хост-операционной системы и её ядра. Это может вызвать проблемы совместимости.

Пример: Windows-контейнеры не могут быть запущены на Linux-системах и наоборот.

5️⃣ Управление состоянием и данными:

Контейнеры лучше всего подходят для безгосударственных приложений. Управление состоянием и данными может быть сложным.

Пример: Работа с постоянными данными требует настройки volume'ов или использование внешних систем хранения данных.

🤔 Краткий ответ

Преимущества использования Docker для .NET приложений включают портативность, изолированность, легкость масштабирования, быстрое развертывание, консистентность среды и упрощенную CI/CD. Недостатки включают сложность изучения, потенциальные накладные расходы на производительность, вопросы безопасности, ограничения хост-системы и сложности управления состоянием и данными.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍71
📌 Что такое атрибуты в C# и какова их основная цель?

💬 Спрашивают в 11% собеседований

🤔 Что такое атрибуты в C#

Атрибуты в C# — это специальные метаданные, которые могут быть добавлены к кодовым элементам (классам, методам, свойствам, полям и т.д.) для предоставления дополнительной информации о них. Эти метаданные могут быть использованы во время выполнения программы с помощью рефлексии для изменения поведения или конфигурации приложения.

🤔 Основная цель атрибутов

1️⃣ Метаданные: Предоставляют дополнительную информацию о кодовых элементах.

2️⃣ Конфигурация: Используются для настройки поведения компонентов и системы.

3️⃣ Валидация: Позволяют валидировать данные и параметры.

4️⃣ Документация: Описывают поведение и характеристики методов и классов.

5️⃣ Интеграция: Обеспечивают взаимодействие с внешними инструментами и библиотеками.

🤔 Примеры использования атрибутов

1️⃣ Пример: Объявление атрибута

Атрибуты объявляются путем создания классов, производных от System.Attribute.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class MyCustomAttribute : Attribute
{
public string Description { get; }

public MyCustomAttribute(string description)
{
Description = description;
}
}


2️⃣ Пример: Применение атрибута

Атрибуты применяются путем указания их над соответствующими кодовыми элементами.
[MyCustomAttribute("This is a sample class")]
public class SampleClass
{
[MyCustomAttribute("This is a sample method")]
public void SampleMethod()
{
// Метод
}
}


3️⃣ Пример: Использование атрибута с помощью рефлексии

Рефлексия используется для получения информации об атрибутах во время выполнения.
using System;
using System.Reflection;

class Program
{
static void Main()
{
Type type = typeof(SampleClass);

// Получение атрибутов класса
object[] classAttributes = type.GetCustomAttributes(false);
foreach (var attr in classAttributes)
{
MyCustomAttribute myAttr = attr as MyCustomAttribute;
if (myAttr != null)
{
Console.WriteLine($"Class Attribute: {myAttr.Description}");
}
}

// Получение атрибутов метода
MethodInfo method = type.GetMethod("SampleMethod");
object[] methodAttributes = method.GetCustomAttributes(false);
foreach (var attr in methodAttributes)
{
MyCustomAttribute myAttr = attr as MyCustomAttribute;
if (myAttr != null)
{
Console.WriteLine($"Method Attribute: {myAttr.Description}");
}
}
}
}


🤔 Встроенные атрибуты

C# и .NET Framework включают множество встроенных атрибутов для различных целей:

1️⃣ Общие атрибуты:

[Obsolete]: Указывает, что элемент устарел.
     [Obsolete("This method is obsolete. Use NewMethod instead.")]
public void OldMethod() { }


2️⃣ Атрибуты для сериализации:

[Serializable]: Указывает, что класс может быть сериализован.
     [Serializable]
public class MySerializableClass { }


3️⃣ Атрибуты для тестирования:

[TestMethod]: Используется в тестовых фреймворках, таких как MSTest, для обозначения метода тестирования.
     [TestMethod]
public void TestMethod1() { }


4️⃣ Атрибуты для ASP.NET:

[HttpGet], [HttpPost]: Указывают, какие HTTP методы поддерживает контроллер в ASP.NET.
     [HttpGet]
public IActionResult Get() { }


🤔 Краткий ответ

Атрибуты в C# — это метаданные, добавляемые к кодовым элементам для предоставления дополнительной информации, конфигурации, валидации и интеграции с внешними инструментами. Они объявляются как классы, производные от System.Attribute, и используются с помощью рефлексии для изменения поведения программы во время выполнения.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11
📌 Что такое reflection и для чего используется?

💬 Спрашивают в 11% собеседований

🤔 Что такое рефлексия (Reflection)

Рефлексия (Reflection) в C# — это механизм, который позволяет программам исследовать и изменять свою структуру и поведение во время выполнения. С помощью рефлексии можно получать информацию о сборках, модулях, типах, методах, свойствах и других элементах кода, а также динамически вызывать методы и создавать экземпляры типов.

🤔 Основные возможности рефлексии

1️⃣ Получение информации о типах: Изучение информации о классах, интерфейсах, структурах, перечислениях и их членах (методах, свойствах, событиях и т.д.).

2️⃣ Динамическое создание объектов: Создание экземпляров классов во время выполнения.

3️⃣ Динамическое вызов методов: Вызов методов и доступ к свойствам и полям объектов динамически.

4️⃣ Изменение метаданных: В некоторых случаях (например, с использованием библиотек типа Mono.Cecil) возможно изменение метаданных сборки.

🤔 Примеры использования рефлексии

🤔 Получение информации о типах
using System;
using System.Reflection;

public class ExampleClass
{
public int ExampleProperty { get; set; }

public void ExampleMethod()
{
Console.WriteLine("Hello from ExampleMethod!");
}
}

class Program
{
static void Main()
{
Type type = typeof(ExampleClass);

// Получение информации о свойствах
PropertyInfo[] properties = type.GetProperties();
foreach (var property in properties)
{
Console.WriteLine($"Property: {property.Name}, Type: {property.PropertyType}");
}

// Получение информации о методах
MethodInfo[] methods = type.GetMethods();
foreach (var method in methods)
{
Console.WriteLine($"Method: {method.Name}");
}
}
}


🤔 Динамическое создание объектов
using System;

public class ExampleClass
{
public void ExampleMethod()
{
Console.WriteLine("Hello from ExampleMethod!");
}
}

class Program
{
static void Main()
{
Type type = typeof(ExampleClass);
object instance = Activator.CreateInstance(type);

MethodInfo method = type.GetMethod("ExampleMethod");
method.Invoke(instance, null); // Вывод: "Hello from ExampleMethod!"
}
}


🤔 Динамическое вызов методов
using System;
using System.Reflection;

public class ExampleClass
{
public void Greet(string name)
{
Console.WriteLine($"Hello, {name}!");
}
}

class Program
{
static void Main()
{
Type type = typeof(ExampleClass);
object instance = Activator.CreateInstance(type);

MethodInfo method = type.GetMethod("Greet");
method.Invoke(instance, new object[] { "World" }); // Вывод: "Hello, World!"
}
}


🤔 Практическое применение рефлексии

1️⃣ Создание систем плагинов: Рефлексия позволяет динамически загружать и использовать плагины или модули, написанные независимо от основной системы.

2️⃣ Сериализация и десериализация: Используется для сериализации объектов в различные форматы (например, JSON, XML) и обратно.

3️⃣ Тестирование: В тестовых фреймворках рефлексия используется для динамического обнаружения и выполнения тестовых методов.

4️⃣ Инспекция и отладка: Рефлексия позволяет инструментам отладки и инспекции анализировать и изменять поведение приложения во время выполнения.

🤔 Краткий ответ

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

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🤯1
🤔 Как предложить избежать deadlock`а?

Избежание deadlock'ов (взаимных блокировок) в многопоточном программировании — важная задача, требующая внимательного проектирования и разработки. Deadlock происходит, когда два или более потока не могут продолжать выполнение, потому что каждый из них ожидает освобождения ресурса, удерживаемого другим потоком. Вот несколько стратегий и методов для предотвращения deadlock'ов:

🚩Избегайте ситуаций, когда один поток удерживает один ресурс и пытается заблокировать другой, уже заблокированный другим потоком. Придерживайтесь простого правила: каждый поток должен блокировать ресурсы в одном и том же порядке.
object lock1 = new object();
object lock2 = new object();

public void Method1()
{
lock (lock1)
{
lock (lock2)
{
// Действия с lock1 и lock2
}
}
}

public void Method2()
{
lock (lock1)
{
lock (lock2)
{
// Действия с lock1 и lock2
}
}
}


🚩Используйте методы блокировки с тайм-аутами, такие как Monitor.TryEnter или Mutex.WaitOne, чтобы предотвратить бесконечное ожидание ресурсов.
object lockObject = new object();

public void MethodWithTimeout()
{
bool lockTaken = false;
try
{
Monitor.TryEnter(lockObject, TimeSpan.FromSeconds(1), ref lockTaken);
if (lockTaken)
{
// Работа с lockObject
}
else
{
// Обработка ситуации, когда блокировка не была взята
}
}
finally
{
if (lockTaken)
{
Monitor.Exit(lockObject);
}
}
}


🚩Вместо тяжеловесных блокировок (lock, Monitor, Mutex), используйте примитивы, которые уменьшают вероятность deadlock'ов, такие как SemaphoreSlim или ReaderWriterLockSlim.
SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);

public async Task MethodWithSemaphore()
{
await semaphore.WaitAsync();
try
{
// Действия, требующие синхронизации
}
finally
{
semaphore.Release();
}
}


🚩Делайте как можно меньше работы внутри критических секций (заблокированных блоков кода). Это уменьшает вероятность столкновения потоков за ресурсы.
object lockObject = new object();

public void Method()
{
// Выполняйте сложные операции вне блока lock
var data = GetData();

lock (lockObject)
{
// Выполняйте только необходимые действия внутри блока lock
ProcessData(data);
}
}

public object GetData()
{
// Долговременная операция
}

public void ProcessData(object data)
{
// Короткая операция
}


🚩Использование асинхронных методов и конструкций, таких как async и await, может помочь уменьшить блокировки потоков.
public async Task MethodAsync()
{
await Task.Run(() =>
{
// Выполнение асинхронной работы
});
}


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