C# | Вопросы собесов
5.1K subscribers
35 photos
1 file
982 links
Download Telegram
🤔 Что бывает, когда количества подключений не хватает?

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

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

🟠Ошибки и исключения
Приложение может выбрасывать исключения, такие как TimeoutException, SqlException (например, Cannot open connection), указывающие на невозможность установления соединения.

🚩Примеры исключений

try
{
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
// Выполнение операций с базой данных
}
}
catch (SqlException ex)
{
Console.WriteLine("Ошибка подключения к базе данных: " + ex.Message);
}
catch (TimeoutException ex)
{
Console.WriteLine("Превышено время ожидания подключения: " + ex.Message);
}


🚩Причины исчерпания подключений

🟠Плохое управление подключениями
Неосвобождение ресурсов: Пул подключений может исчерпаться, если подключения не закрываются и не возвращаются в пул после использования. Длительное удержание подключений: Подключения удерживаются слишком долго, например, при выполнении долгих операций в одной сессии.
🟠Высокая нагрузка
Чрезмерное количество одновременно выполняемых запросов, превышающее максимальное количество доступных подключений в пуле.
🟠Неправильная настройка пула подключений
Недостаточное количество максимальных подключений в пуле или слишком большое время ожидания подключения.

🚩Способы решения проблемы

🟠Правильное управление подключениями
Всегда закрывайте соединения после использования, чтобы они возвращались в пул.
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
// Выполнение операций с базой данных
connection.Close(); // Явно закрываем подключение
}


Используйте конструкцию using для автоматического закрытия соединений.
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
// Выполнение операций с базой данных
} // Подключение автоматически закрывается здесь


🟠Настройка пула подключений
Увеличьте максимальное количество подключений в пуле.
var connectionString = "Data Source=server;Initial Catalog=database;User ID=user;Password=password;Max Pool Size=100;";


Настройте время ожидания подключения.
var connectionString = "Data Source=server;Initial Catalog=database;User ID=user;Password=password;Connection Timeout=30;";


🟠Оптимизация запросов и транзакций
Минимизируйте время удержания соединений. Используйте транзакции эффективно, чтобы не блокировать соединения на долгое время.
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
using (var transaction = connection.BeginTransaction())
{
try
{
// Выполнение операций с базой данных
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
}


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

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

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

В ASP.NET Core можно выполнять действия до и после обработки запроса, не используя middleware, с помощью фильтров действий (Action Filters). Фильтры позволяют выполнять код до и после вызова метода контроллера.

🚩Фильтры действий (Action Filters)

🟠Создание фильтра действия
Создадим фильтр, который выполняет код до и после метода действия контроллера.
using Microsoft.AspNetCore.Mvc.Filters;
using System;

public class MyActionFilter : Attribute, IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
// Код, выполняемый до действия контроллера
Console.WriteLine("До выполнения действия контроллера.");
}

public void OnActionExecuted(ActionExecutedContext context)
{
// Код, выполняемый после действия контроллера
Console.WriteLine("После выполнения действия контроллера.");
}
}


🟠Применение фильтра к контроллеру или действию
Фильтр можно применить к конкретному методу контроллера или ко всему контроллеру.
using Microsoft.AspNetCore.Mvc;

public class MyController : Controller
{
[MyActionFilter]
public IActionResult MyAction()
{
// Логика действия контроллера
return Ok("Action executed");
}
}


Применение ко всему контроллеру
using Microsoft.AspNetCore.Mvc;

[MyActionFilter]
public class MyController : Controller
{
public IActionResult MyAction1()
{
// Логика действия контроллера
return Ok("Action 1 executed");
}

public IActionResult MyAction2()
{
// Логика действия контроллера
return Ok("Action 2 executed");
}
}


🟠Применение глобального фильтра
Фильтр также можно зарегистрировать глобально, чтобы он применялся ко всем контроллерам и действиям. Регистрация глобального фильтра в Startup.cs
using Microsoft.AspNetCore.Mvc;

public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options =>
{
options.Filters.Add<MyActionFilter>();
});
}


🚩Пример выполнения действий до и после запроса

Создание фильтра
using Microsoft.AspNetCore.Mvc.Filters;
using System;

public class LoggingActionFilter : Attribute, IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
// Логика до выполнения действия контроллера
Console.WriteLine("Запрос начался: " + context.HttpContext.Request.Path);
}

public void OnActionExecuted(ActionExecutedContext context)
{
// Логика после выполнения действия контроллера
Console.WriteLine("Запрос завершился: " + context.HttpContext.Request.Path);
}
}


Применение фильтра к контроллеру
using Microsoft.AspNetCore.Mvc;

[LoggingActionFilter]
public class UsersController : Controller
{
public IActionResult GetUser(int id)
{
// Логика действия контроллера
return Ok(new { Id = id, Name = "User" + id });
}
}


Регистрация в Startup.cs
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

app.UseRouting();

app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}


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

Сервис-локатор — это паттерн проектирования, который предоставляет центральный реестр для поиска и получения экземпляров зависимостей или сервисов.
Класс сервис-локатора хранит ссылки на сервисы и позволяет запрашивать их по идентификатору, что упрощает управление зависимостями.
Однако этот паттерн критикуют за скрытые зависимости и нарушение принципа инверсии зависимостей (SOLID).


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

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

🚩Базовые сущности

🟠Сообщения (Messages)
Это данные, которые отправляются от отправителя к получателю через RabbitMQ. Сообщения могут содержать любые данные: текст, JSON, XML, двоичные данные и т.д.

🟠Очереди (Queues)
Э
то места, где сообщения хранятся до тех пор, пока их не заберет получатель. Очереди обеспечивают надежную доставку сообщений и поддерживают множество получателей.
Создание очереди
rabbitmqadmin declare queue name=my_queue durable=true


🟠Обменники (Exchanges)
Принимают сообщения от отправителей и направляют их в соответствующие очереди на основе правил маршрутизации. Существует несколько типов обменников:
Direct: Сообщения направляются в очередь с ключом маршрутизации, точно соответствующим ключу, указанному в обменнике.
Fanout: Сообщения направляются во все очереди, связанные с этим обменником, без учета ключа маршрутизации.
Topic: Сообщения направляются в очереди на основе шаблонов ключей маршрутизации.
Headers: Сообщения направляются в очереди на основе соответствия заголовков.
Создание обменника:
rabbitmqadmin declare exchange name=my_exchange type=direct durable=true


🟠Связи (Bindings)
Определяют правила маршрутизации между обменниками и очередями. Они указывают, какие ключи маршрутизации должны использоваться для доставки сообщений из обменника в очередь.
Создание связи
rabbitmqadmin declare binding source=my_exchange destination=my_queue routing_key=my_key


🟠Ключи маршрутизации (Routing Keys)
Ключи маршрутизации используются обменниками для определения, в какие очереди направлять сообщения. Они играют ключевую роль при использовании direct и topic обменников.

🟠Потребители (Consumers)
Это приложения или службы, которые получают сообщения из очередей и обрабатывают их. Пример производителя на Python
import pika

def callback(ch, method, properties, body):
print(f"Received {body}")

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

channel.queue_declare(queue='my_queue')

channel.basic_consume(queue='my_queue', on_message_callback=callback, auto_ack=True)

print('Waiting for messages. To exit press CTRL+C')
channel.start_consuming()


🟠Производители (Producers)
Э
то приложения или службы, которые отправляют сообщения в обменники RabbitMQ. Пример производителя на Python
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

channel.queue_declare(queue='my_queue')

channel.basic_publish(exchange='', routing_key='my_queue', body='Hello World!')

print(" [x] Sent 'Hello World!'")
connection.close()


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

get — это метод или функция, используемая для получения значения из объекта, коллекции или свойства.
В языке Python, например, метод get применяется к словарям для безопасного извлечения значения по ключу, возвращая None или значение по умолчанию, если ключ отсутствует.
В JavaScript get может быть геттером, определяющим, как получить значение свойства объекта при его доступе.


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

Типы данных можно классифицировать по нескольким критериям, включая базовые категории, такие как значимые типы (value types) и ссылочные типы (reference types), а также другие характеристики, такие как встроенные типы, пользовательские типы и системы типов.

🚩Классификации типов

🟠Значимые типы (Value Types)
Значимые типы хранят свои значения непосредственно и обычно располагаются в стеке. При присваивании переменной значимого типа другой переменной создается копия значения.
int a = 10;
int b = a; // b получит копию значения a


🟠Структуры (struct)
Пользовательские типы, которые объединяют несколько значений.
struct Point
{
public int X;
public int Y;
}

Point p1 = new Point { X = 1, Y = 2 };
Point p2 = p1; // p2 получит копию значений p1


🟠Перечисления (enum)
Типы, представляющие набор именованных констант.
enum Days { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday };
Days today = Days.Monday;


🟠Ссылочные типы (Reference Types)
Ссылочные типы хранят ссылки на объекты, которые располагаются в куче (heap). При присваивании переменной ссылочного типа другой переменной копируется ссылка на объект, а не сам объект.

🟠Классы (class)
Основные строительные блоки объектов.
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}

Person p1 = new Person { Name = "Alice", Age = 30 };
Person p2 = p1; // p2 указывает на тот же объект, что и p1


🟠Интерфейсы (interface)
Контракты, определяющие набор методов и свойств, которые должны быть реализованы классами.
interface IAnimal
{
void Speak();
}

class Dog : IAnimal
{
public void Speak() => Console.WriteLine("Woof!");
}


🟠Делегаты (delegate)
Типы, представляющие ссылки на методы.
delegate void MyDelegate(string message);
MyDelegate del = Console.WriteLine;
del("Hello, World!");


🟠Массивы (arrays)
Коллекции элементов одного типа.
int[] numbers = new int[] { 1, 2, 3, 4, 5 };  


🟠Строки (string)
Последовательности символов.
string greeting = "Hello, World!";  


🟠Nullable типы
Nullable типы позволяют значимым типам принимать значение null, что означает отсутствие значения.
int? nullableInt = null;  


🟠Обобщенные типы (Generics)
Обобщенные типы позволяют создавать классы, методы и структуры, которые могут работать с любыми типами данных, обеспечивая типобезопасность и повторное использование кода.
class GenericClass<T>
{
public T Value { get; set; }
}

GenericClass<int> intInstance = new GenericClass<int> { Value = 10 };
GenericClass<string> stringInstance = new GenericClass<string> { Value = "Hello" };


🟠Неуправляемые типы (Unsafe Types)
Неуправляемые типы позволяют работать с указателями и выполнять низкоуровневые операции, которые обычно не разрешены в безопасном управляемом коде.
unsafe
{
int x = 10;
int* ptr = &x;
Console.WriteLine((int)ptr); // Вывод адреса переменной x
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
9👍2
🤔 В чём разница абстрактного класса и интерфейса?

Абстрактный класс может содержать как реализацию методов, так и абстрактные методы, а интерфейс — только определения методов без реализации. Абстрактные классы могут иметь поля и конструкторы, а интерфейсы — нет. Класс может наследовать только один абстрактный класс, но реализовать несколько интерфейсов. Интерфейсы предоставляют более гибкий способ организации контракта для классов.

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

🚩Стек

Значимые типы обычно хранятся на стеке, когда они объявлены внутри метода. Это происходит потому, что стек обеспечивает быстрый доступ и автоматическое управление памятью.
void MyMethod()
{
int localVar = 10; // localVar хранится на стеке
}


🚩Куча

Значимые типы могут храниться в куче, если они являются частью объекта ссылочного типа. Например, если структура или переменная типа int является полем класса, то она будет храниться в куче вместе с объектом класса.
class MyClass
{
public int Number; // Number хранится в куче, потому что MyClass - ссылочный тип
}

MyClass obj = new MyClass();
obj.Number = 42;


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

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

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

Существует два способа избежать упаковки и распаковки (boxing и unboxing) значимых типов при их хранении в коллекциях или использовании в других ситуациях, где тип данных не должен быть упакован в объект.

🟠Использование обобщений (generics)
Обобщения позволяют создавать коллекции и методы, которые работают с любыми типами данных без необходимости упаковки.
// Пример использования обобщённого списка для значимого типа int
List<int> numbers = new List<int>();
numbers.Add(10); // Добавление без упаковки

int number = numbers[0]; // Чтение без распаковки


🟠Использование специальных структур
В некоторых случаях для избежания упаковки можно создать специальные структуры, которые содержат необходимые данные и методы.
// Обобщённый метод для работы с любыми типами данных без упаковки
public T FindMax<T>(T a, T b) where T : IComparable<T>
{
return a.CompareTo(b) > 0 ? a : b;
}

// Использование метода для значимого типа int
int max = FindMax(3, 5);
Console.WriteLine(max); // Выведет: 5


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

Стек — это структура данных LIFO, где последний добавленный элемент извлекается первым, используется для вызовов функций и хранения локальных данных.
Чем отличается метод Equal от ==? Equals проверяет логическое равенство объектов, а == сравнивает ссылки для объектов и значения для примитивов.


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

🟠Ссылочный тип
string является ссылочным типом, хотя по поведению он похож на значимый тип. Это означает, что переменная типа string содержит ссылку на объект строки, хранящийся в памяти, а не непосредственно данные.

🟠Иммутабельность (неизменяемость)
Объекты типа string неизменяемы. Это означает, что после создания строки её содержимое нельзя изменить. Любые операции, которые кажутся изменяющими строку (например, Replace, Substring), на самом деле создают новую строку.
string original = "Hello";
string modified = original.Replace('H', 'J'); // Создаётся новая строка "Jello"


🟠Поддержка операторов и методов
string поддерживает различные операторы и методы для работы с текстом. Например, оператор + для конкатенации строк, метод Substring для извлечения подстрок, метод Split для разбиения строки и т.д.
string hello = "Hello";
string world = "World";
string concatenated = hello + " " + world; // "Hello World"


🟠Интернирование строк
Для оптимизации памяти строки могут интернироваться. Это означает, что строки с одинаковым содержимым могут храниться в единственном экземпляре в пуле строк.
string a = "test";
string b = "test";
bool areEqual = object.ReferenceEquals(a, b); // True, потому что строки интернированы


🟠Специальная поддержка в языке
string имеет специальную поддержку на уровне языка. Например, строковые литералы в коде автоматически рассматриваются как объекты типа string.
string greeting = "Hello, world!";   


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
🤔 Есть ref out и boxing unboxing в чем их разница?

ref передаёт переменные по ссылке, out требует их инициализации в методе, boxing/unboxing преобразуют тип значения в объект и обратно.

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

Сравнение содержимого объектов классов в C# можно выполнить несколькими способами. Наиболее распространенные методы включают переопределение методов Equals и GetHashCode, а также реализацию интерфейса IEquatable<T> и использование библиотек для глубокого сравнения.

🟠Переопределение методов Equals и GetHashCode
Для сравнения содержимого классов можно переопределить методы Equals и GetHashCode. Это позволяет определить логику сравнения объектов на основе их полей.
public class Person
{
public string Name { get; set; }
public int Age { get; set; }

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

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

public override int GetHashCode()
{
return HashCode.Combine(Name, Age);
}
}


🟠Реализация интерфейса IEquatable<T>
Позволяет улучшить производительность сравнения и сделать код более читаемым.
public class Person : IEquatable<Person>
{
public string Name { get; set; }
public int Age { get; set; }

public bool Equals(Person other)
{
if (other == null)
return false;

return Name == other.Name && Age == other.Age;
}

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

return Equals((Person)obj);
}

public override int GetHashCode()
{
return HashCode.Combine(Name, Age);
}
}


🟠Использование библиотек для глубокого сравнения
Существуют библиотеки, такие как DeepEqual или Json.NET, которые позволяют выполнять глубокое сравнение объектов, автоматически сравнивая все их поля и свойства.
using KellermanSoftware.CompareNetObjects;

public class Program
{
public static void Main()
{
Person person1 = new Person { Name = "Alice", Age = 30 };
Person person2 = new Person { Name = "Alice", Age = 30 };

var compareLogic = new CompareLogic();
ComparisonResult result = compareLogic.Compare(person1, person2);

Console.WriteLine(result.AreEqual); // True
}
}


🟠Сравнение через сериализацию
Ещё один способ сравнить содержимое объектов - это сериализовать их в JSON и затем сравнить полученные строки.
using Newtonsoft.Json;

public class Program
{
public static void Main()
{
Person person1 = new Person { Name = "Alice", Age = 30 };
Person person2 = new Person { Name = "Alice", Age = 30 };

string json1 = JsonConvert.SerializeObject(person1);
string json2 = JsonConvert.SerializeObject(person2);

bool areEqual = json1 == json2;
Console.WriteLine(areEqual); // True
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14
🤔 Чем отличается метод Equal от ==?

Equals проверяет логическое равенство объектов, а == сравнивает ссылки для объектов и значения для примитивов.

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

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

🟠Тип данных
Классы: являются ссылочными типами (reference types). Переменные класса хранят ссылки на объекты, которые размещены в куче (heap).
Структуры: являются значимыми типами (value types). Переменные структуры хранят сами данные, и эти данные размещаются на стеке (stack) или в куче, если структура является частью объекта класса.

🟠Передача данных
Классы: при передаче объекта класса по значению (например, в метод) передается ссылка на объект, а не сам объект.
Структуры: при передаче структуры по значению передается копия всех данных структуры.

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

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

🟠Размер и производительность
Классы: из-за размещения в куче и необходимости сборки мусора (garbage collection) могут быть медленнее при частом создании и удалении объектов.
Структуры: часто эффективнее по памяти и времени выполнения для небольших объектов, которые создаются и уничтожаются часто, благодаря размещению на стеке.

🟠Индивидуальные особенности
Классы: поддерживают полиморфизм, виртуальные методы, события и делегаты.
Структуры: обычно применяются для небольших, неизменяемых объектов. Не могут содержать деструкторы и не поддерживают наследование, кроме интерфейсов.

🚩Пример

Класса
public class Person
{
public string Name { get; set; }
public int Age { get; set; }

public Person(string name, int age)
{
Name = name;
Age = age;
}
}


Структуры
public struct Point
{
public int X { get; set; }
public int Y { get; set; }

public Point(int x, int y)
{
X = x;
Y = y;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
🤔 В чём отличие thread от task?

Thread — это поток ОС, а Task — абстракция для работы с асинхронным кодом, которая легче и управляется планировщиком.

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

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

🚩Когда использовать

🟠Наследование и полиморфизм
Используйте классы, когда требуется наследование (один класс наследуется от другого) или полиморфизм (переменная может принимать значения различных типов, связанных наследованием).
public class Animal
{
public virtual void MakeSound() { }
}

public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Bark");
}
}


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

🟠Изменяемые объекты
Классы подходят для объектов, которые должны изменяться после создания, так как они являются ссылочными типами и изменения будут видны всем, кто имеет ссылку на объект.

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

🚩Когда использовать

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

🟠Значимые типы
Если объект представляет собой значение, которое логически является единым целым (например, координаты точки, комплексное число), структура подходит лучше.

🟠Производительность
Структуры могут быть эффективнее классов в ситуациях, где часто создаются и уничтожаются небольшие объекты, поскольку они хранятся на стеке и не требуют сборки мусора.

🟠Отсутствие наследования
Если нет необходимости в наследовании, структуры могут быть удобнее и проще для использования.

🚩Примеры

Использование класса
public class Car
{
public string Make { get; set; }
public string Model { get; set; }
public int Year { get; set; }

public void StartEngine()
{
Console.WriteLine("Engine started");
}
}


Использование структуры
public struct Point
{
public int X { get; }
public int Y { get; }

public Point(int x, int y)
{
X = x;
Y = y;
}
}


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

Сборщик мусора удаляет объекты, на которые нет ссылок, оптимизируя использование памяти.

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

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

🚩Когда использовать интерфейсы

🟠Множественное наследование
Класс может реализовывать несколько интерфейсов, но наследоваться только от одного класса. Используйте интерфейсы, когда требуется множественное наследование.
public interface IDriveable
{
void Drive();
}

public interface IFlyable
{
void Fly();
}

public class FlyingCar : IDriveable, IFlyable
{
public void Drive() { /* Реализация вождения */ }
public void Fly() { /* Реализация полета */ }
}


🟠Общее поведение без реализации
Используйте интерфейсы, чтобы определить общий набор методов и свойств без предоставления какой-либо реализации. Это позволяет разным классам реализовать интерфейс по-своему.
public interface IShape
{
double GetArea();
}

public class Circle : IShape
{
public double Radius { get; set; }
public double GetArea() => Math.PI * Radius * Radius;
}

public class Rectangle : IShape
{
public double Width { get; set; }
public double Height { get; set; }
public double GetArea() => Width * Height;
}


🟠Гибкость и полиморфизм
Интерфейсы позволяют легко менять реализацию и обеспечивают гибкость в коде. Можно использовать интерфейсы для создания полиморфных коллекций или методов, которые работают с разными реализациями интерфейсов.
public void DrawShapes(IEnumerable<IShape> shapes)
{
foreach (var shape in shapes)
{
Console.WriteLine($"Area: {shape.GetArea()}");
}
}


🚩Когда использовать

🟠Частичная реализация
Используйте абстрактные классы, если вы хотите предоставить некоторую общую реализацию, которую могут использовать подклассы. Абстрактные классы могут содержать как абстрактные, так и не абстрактные методы.
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");
}


🟠Шаблонный метод
Абстрактные классы хорошо подходят для реализации паттерна "Шаблонный метод", где общий алгоритм реализован в абстрактном классе, а конкретные шаги определены в подклассах.
public abstract class Game
{
public void Play()
{
Initialize();
StartPlay();
EndPlay();
}

protected abstract void Initialize();
protected abstract void StartPlay();
protected abstract void EndPlay();
}

public class Football : Game
{
protected override void Initialize() => Console.WriteLine("Football Game Initialized");
protected override void StartPlay() => Console.WriteLine("Football Game Started");
protected override void EndPlay() => Console.WriteLine("Football Game Ended");
}


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