Инверсия зависимостей — это принцип SOLID, который говорит:
> Модули верхнего уровня не должны зависеть от модулей нижнего уровня. Оба должны зависеть от абстракций.
Это значит, что вместо жёстких зависимостей на конкретные классы, код должен работать через абстракции (
interface или abstract class). Допустим, у нас есть класс
EmailSender, который отправляет письма:public class EmailSender
{
public void Send(string message)
{
Console.WriteLine($"Отправка email: {message}");
}
}
public class NotificationService
{
private EmailSender _emailSender = new EmailSender();
public void Notify(string message)
{
_emailSender.Send(message);
}
}
Чтобы избавиться от жёсткой зависимости, вводим абстракцию (
IMessageSender):public interface IMessageSender
{
void Send(string message);
}
public class EmailSender : IMessageSender
{
public void Send(string message)
{
Console.WriteLine($"Отправка email: {message}");
}
}
public class SmsSender : IMessageSender
{
public void Send(string message)
{
Console.WriteLine($"Отправка SMS: {message}");
}
}
Теперь
NotificationService зависит не от конкретного класса, а от интерфейса:public class NotificationService
{
private readonly IMessageSender _messageSender;
public NotificationService(IMessageSender messageSender)
{
_messageSender = messageSender;
}
public void Notify(string message)
{
_messageSender.Send(message);
}
}
Теперь мы можем подставлять любую реализацию
IMessageSender: var emailNotifier = new NotificationService(new EmailSender());
emailNotifier.Notify("Привет через Email!");
var smsNotifier = new NotificationService(new SmsSender());
smsNotifier.Notify("Привет через SMS!");
Вывод
Отправка email: Привет через Email!
Отправка SMS: Привет через SMS!
Гибкость – можно легко заменять зависимости.
Тестируемость – можно подставить Mock-объект вместо
EmailSender. Меньше изменений в коде – можно добавить новые способы отправки сообщений без изменения
NotificationService.Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Forwarded from Идущий к IT
🔥 Записал видос "Как за 3 минуты настроить Автоотклики на вакансии HeadHunter" больше не придется заниматься этой унылой рутиной
📺 Видео: https://youtu.be/G_FOwEGPwlw
Please open Telegram to view this post
VIEW IN TELEGRAM
В этом случае нужно использовать полное имя интерфейсов с указанием пространства имён (namespace).
Это позволяет разграничить их и избежать конфликта.
Если нужно реализовать оба в одном классе, возможна явная реализация, чтобы уточнить, к какому интерфейсу относится метод.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
В .NET среде управления памятью, объекты размещаются в куче (heap), и управление памятью осуществляется сборщиком мусора (Garbage Collector, GC). Куча разделена на несколько поколений для оптимизации производительности управления памятью.
Куча в .NET разделена на три поколения: Generation 0, Generation 1 и Generation 2. Это разделение позволяет эффективно управлять памятью, минимизируя частоту сборок мусора и оптимизируя их выполнение.
Содержит новосозданные объекты. Сборка мусора для этого поколения происходит чаще, так как большинство объектов "умирает" быстро. Наименьший размер среди всех поколений.
Промежуточное поколение, используемое для объектов, которые пережили хотя бы одну сборку мусора Generation 0. Содержит объекты с более длительным временем жизни, чем объекты в Generation 0.
Содержит объекты с самым длительным временем жизни. Наибольший размер среди всех поколений. Сборка мусора для этого поколения происходит реже всего.
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
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
1. Они полезны для предотвращения ошибок, например, удаления связанных записей.
2. Однако в некоторых случаях (например, масштабируемые системы) можно использовать программную логику вместо внешних ключей для повышения производительности.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
В ASP.NET Core методы Service Configuration используются для настройки и регистрации зависимостей в контейнере внедрения зависимостей (Dependency Injection, DI). Это позволяет управлять зависимостями в приложении, делая код более гибким, тестируемым и удобным для расширения.
Настройка сервисов выполняется в методе
ConfigureServices(IServiceCollection services), который находится в классе Program.cs или Startup.cs (в зависимости от версии .NET). public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(); // Добавление контроллеров для API
services.AddDbContext<ApplicationDbContext>(); // Регистрация контекста базы данных
services.AddScoped<IMyService, MyService>(); // Внедрение зависимости
}
создаёт единственный экземпляр объекта на всё время работы приложения.
services.AddSingleton<ILogger, ConsoleLogger>();
создаёт один экземпляр объекта на каждый HTTP-запрос.
services.AddScoped<IUserService, UserService>();
создаёт новый экземпляр объекта при каждом запросе.
services.AddTransient<IEmailSender, EmailSender>();
public class HomeController : Controller
{
private readonly IMyService _myService;
public HomeController(IMyService myService)
{
_myService = myService;
}
public IActionResult Index()
{
var data = _myService.GetData();
return View(data);
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1💊1
В C# ключевые слова
ref и out используются для передачи аргументов по ссылке, что позволяет методам изменять значения этих аргументов. Эти механизмы полезны как для значимых типов (структур), так и для ссылочных типов (объектов). Давайте рассмотрим более детально, зачем и как их используют для ссылочных типов.С помощью
ref можно передавать ссылочные типы таким образом, чтобы метод мог изменять саму ссылку, то есть ссылаться на другой объект.Ключевое слово
out позволяет передавать аргумент, который не обязательно должен быть инициализирован до вызова метода. Метод, принимающий out аргумент, обязан присвоить ему значение до завершения работы.Пример использования
ref class Program
{
static void ChangeReference(ref MyClass obj)
{
obj = new MyClass { Value = 20 };
}
static void Main()
{
MyClass myObj = new MyClass { Value = 10 };
ChangeReference(ref myObj);
Console.WriteLine(myObj.Value); // Output: 20
}
}
class MyClass
{
public int Value { get; set; }
}
Пример использования
out class Program
{
static void InitializeObject(out MyClass obj)
{
obj = new MyClass { Value = 30 };
}
static void Main()
{
MyClass myObj;
InitializeObject(out myObj);
Console.WriteLine(myObj.Value); // Output: 30
}
}
class MyClass
{
public int Value { get; set; }
}
ref и out добавляют гибкости при работе с методами, позволяя им изменять ссылки на объекты или создавать и возвращать новые объекты.Эти механизмы могут быть полезны для оптимизации, когда необходимо избежать лишнего копирования данных, особенно при работе с большими объектами.
out полезен для методов, которые должны вернуть несколько значений или инициализировать объекты, которые не могут быть инициализированы заранее.Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🔥1
1. Она позволяет браузеру найти нужный сервер по имени.
2. Использует иерархическую структуру, начиная с корневых серверов.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Это структура данных, используемая в системах управления базами данных (СУБД) для организации и ускорения доступа к данным. B-tree индекс является сбалансированным деревом, обеспечивающим эффективное выполнение операций поиска, вставки, удаления и диапазонного поиска. B-tree индекс используется большинством реляционных СУБД, таких как SQL Server, MySQL, PostgreSQL и Oracle.
B-tree индекс является сбалансированным деревом, где все листья находятся на одном уровне. Это обеспечивает равномерное время доступа к данным.
В узлах B-tree хранятся ключи, которые могут ссылаться на строки в таблице или на другие узлы дерева.
Ключи в каждом узле упорядочены, что позволяет эффективно выполнять бинарный поиск внутри узла.
B-tree индекс эффективно поддерживает диапазонные запросы (например, поиск всех записей с ключами между заданными значениями).
B-tree автоматически сбалансирован, что позволяет эффективно выполнять операции вставки, удаления и обновления.
CREATE TABLE Employees (
EmployeeID INT PRIMARY KEY,
FirstName VARCHAR(50),
LastName VARCHAR(50),
DepartmentID INT,
Salary DECIMAL(10, 2)
);
CREATE INDEX idx_lastname ON Employees(LastName);
Операция поиска в B-tree выполняется за логарифмическое время O(log n), где n — количество узлов.
SELECT * FROM Employees WHERE LastName = 'Smith';
Диапазонные запросы, такие как поиск всех сотрудников с фамилией от 'A' до 'M', выполняются эффективно.
SELECT * FROM Employees WHERE LastName BETWEEN 'A' AND 'M';
При вставке новой записи в таблицу с индексом B-tree, запись добавляется в соответствующее место, поддерживая балансировку дерева.
INSERT INTO Employees (EmployeeID, FirstName, LastName, DepartmentID, Salary)
VALUES (1, 'John', 'Doe', 10, 60000.00);
При удалении записи соответствующий ключ удаляется из B-tree, и дерево автоматически перестраивается, чтобы сохранить балансировку.
DELETE FROM Employees WHERE EmployeeID = 1;
Обеспечивает быстрый доступ к данным благодаря сбалансированной структуре дерева.
Поддерживает операции вставки, удаления и поиска с логарифмической сложностью.
Эффективно обрабатывает диапазонные запросы благодаря упорядоченной структуре.
Динамическая балансировка дерева обеспечивает равномерное время доступа и вставки/удаления.
Требует дополнительного пространства для хранения структуры дерева и ключей.
Вставка и удаление могут требовать перестроения узлов, что влечет за собой дополнительные вычислительные затраты.
При частых операциях вставки и удаления может возникнуть фрагментация, что может потребовать периодического обслуживания (например, реорганизации индекса).
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
"Ты че, дурак?" – базовая реакция сеньора на тех, кто покупает IT курсы
Дело в том, что онлайн школы создают инкубаторных айтишников, которые в реальных условиях попросту зависнут.
Трушные ребята учатся на жизненных каналах для айтишников. Вот топ-5 от тимлида из Сбера:
⚙️ Технолоджия – для тех, кто хочет быть в курсе новостей в айти
🧠 Ai-чница – способы превратить нейросети в заработок $$$
💻 ИИ тебя заменит! – тенденции айти рынка в связке с нейросетями
4️⃣ Войти в IT – тонны бесплатного обучения для прогеров
😄 IT индус – сборник айти мемов
Дело в том, что онлайн школы создают инкубаторных айтишников, которые в реальных условиях попросту зависнут.
Трушные ребята учатся на жизненных каналах для айтишников. Вот топ-5 от тимлида из Сбера:
Please open Telegram to view this post
VIEW IN TELEGRAM
💊2🔥1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4
Нет, структура (
struct) не становится ссылочным типом, даже если мы передаём её через ref или out. Однако, когда структура передаётся с ref или out, передаётся сама структура (по ссылке), а не её копия. Это позволяет изменять исходный объект напрямую, избегая копирования.Передача структуры без
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 работает так же, как ref, но требует обязательной инициализации внутри метода.void InitPoint(out Point p)
{
p = new Point { X = 50, Y = 50 }; // Обязательно присвоить значение
}
Point newPoint;
InitPoint(out newPoint);
Console.WriteLine(newPoint.X); // 50
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊3🔥1
Для получения значения по ключу в словаре (
Dictionary<TKey, TValue>) используются методы и свойства, такие как индексатор [], метод TryGetValue, и метод ContainsKey. Индексатор позволяет получить значение по ключу напрямую. Если ключ отсутствует в словаре, будет выброшено исключение
KeyNotFoundException.var dictionary = new Dictionary<int, string>
{
{ 1, "One" },
{ 2, "Two" },
{ 3, "Three" }
};
try
{
string value = dictionary[2]; // Получение значения по ключу 2
Console.WriteLine(value); // Выведет "Two"
}
catch (KeyNotFoundException)
{
Console.WriteLine("Key not found");
}
Метод
TryGetValue позволяет безопасно получить значение по ключу. Он возвращает true, если ключ найден, и false, если ключ отсутствует. При этом значение записывается в выходной параметр.var dictionary = new Dictionary<int, string>
{
{ 1, "One" },
{ 2, "Two" },
{ 3, "Three" }
};
if (dictionary.TryGetValue(2, out string value))
{
Console.WriteLine(value); // Выведет "Two"
}
else
{
Console.WriteLine("Key not found");
}
Метод
ContainsKey проверяет наличие ключа в словаре. Его можно использовать в сочетании с индексатором для получения значения.var dictionary = new Dictionary<int, string>
{
{ 1, "One" },
{ 2, "Two" },
{ 3, "Three" }
};
if (dictionary.ContainsKey(2))
{
string value = dictionary[2];
Console.WriteLine(value); // Выведет "Two"
}
else
{
Console.WriteLine("Key not found");
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM