C# | Вопросы собесов
5.1K subscribers
36 photos
1 file
990 links
Download Telegram
🤔 Что такое индексы, какие типы бывают, использовал ли их на практике?

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

🚩Типы

🟠Одиночные индексы (Single-column indexes)
Индексируют значения одного столбца таблицы. Это основной тип индекса, используемый для ускорения запросов, фильтрующих или сортирующих данные по одному столбцу.

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

🟠Уникальные индексы (Unique indexes)
Гарантируют, что индексируемые значения уникальны. Они часто используются для обеспечения уникальности столбцов или набора столбцов в таблице.

🟠Полнотекстовые индексы (Full-text indexes)
Позволяют проводить полнотекстовый поиск по текстовым данным в базе данных. Они оптимизированы для поиска слов в больших текстовых полях и часто используются в системах, где требуется поиск по содержимому статей, блогов и других текстовых документов.

🟠Пространственные индексы (Spatial indexes)
Используются для индексации пространственных данных, таких как географические объекты. Они оптимизируют запросы, включающие пространственные операции, такие как нахождение объектов внутри заданной области.

🚩Осмысленное использование

🟠Анализ запросов
Использование индексов должно начинаться с анализа наиболее часто выполняемых запросов и понимания структуры данных. Профилирование и анализ планов выполнения запросов помогут определить, где индексы могут быть полезны.

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

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

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1
🤔 Для чего нужно разделение в куче на три поколения?

Разделение памяти кучи на три поколения (Generation 0, 1, 2) в сборщике мусора (Garbage Collector, GC) помогает оптимизировать очистку памяти.
- Generation 0 – содержит объекты, которые создаются недавно и быстро умирают. Очистка происходит часто и быстро.
- Generation 1 – промежуточное поколение для объектов, которые пережили первую сборку мусора.
- Generation 2 – для долгоживущих объектов, которые редко удаляются (например, кеши, синглтоны). Очистка происходит реже, но дольше.


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

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

🚩`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;
}
}


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

Сборка мусора в .NET запускается автоматически по трем основным причинам:
1. Когда выделяется слишком много памяти в Generation 0.
2. Если приложение выполняет GC.Collect(), но это не рекомендуется без необходимости.
3. Когда система испытывает нехватку памяти и операционная система сигнализирует об этом.
GC использует алгоритмы Mark-and-Sweep и Compact, удаляя объекты, на которые нет ссылок, и сжимая память.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥2
🤔 Приведи пример паттерна строитель в С#

Паттерн "Строитель" (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


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

Конкурентные коллекции позволяют безопасно работать с данными в многопоточной среде:
- ConcurrentDictionary<TKey, TValue> – потокобезопасный словарь.
- ConcurrentQueue<T> – потокобезопасная очередь FIFO.
- ConcurrentStack<T> – потокобезопасный стек LIFO.
- BlockingCollection<T> – использует внутреннюю коллекцию с возможностью блокировки при добавлении или извлечении.
- ConcurrentBag<T> – потокобезопасная неупорядоченная коллекция.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4👍2
Forwarded from easyoffer
На easyoffer 2.0 появится новый раздел:
Задачи с собеседований

🟠Задачи на Алгоритмические, Live-coding и System Design из реальных собеседований
🟠Вероятность встретить ту или иную задачу
🟠Возможность подготовиться к задачам конкретной компании

Есть много сайтов, на которых можно тренироваться решать задачи, но у них у всех одна проблема – сами задачи люди просто выдумывают. На easyoffer 2.0 вы сможете готовиться к live-coding и system design секциям на основе задач из реальных собеседований. Вы можете найдете самые частые задачи и сделаете упор на их решение.

Считаные дни остались до старта краудфандинговой кампании, чтобы ускорить разработку easyoffer 2.0. Все кто, поддержал проект на этом этапе смогу получить 1 год доступа к сайту по цене месячной подписки, а те кто поддержат проект раньше других ито дешевле + получат существенный бонус. Следите за стартом 👉 в этом телеграм канале.
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Интерполяция - это возможность использовать в строке переменные?

Да, интерполяция строк — это удобный способ вставки значений переменных в строку без использования конкатенации (+) или String.Format().

Простой пример интерполяции строк
string name = "Иван";
int age = 25;

string message = $"Привет, меня зовут {name}, и мне {age} лет.";
Console.WriteLine(message);


Вывод
Привет, меня зовут Иван, и мне 25 лет.


🚩Дополнительные возможности интерполяции

🟠Форматирование значений
Можно форматировать числа и даты прямо в строке:
double price = 99.99;
DateTime today = DateTime.Now;

string formatted = $"Цена: {price:C}, Дата: {today:dd.MM.yyyy}";
Console.WriteLine(formatted);


Вывод
Цена: 99,99 ₽, Дата: 01.03.2025


🟠Выполнение выражений
Можно вставлять даже арифметические операции и вызовы методов:
int a = 10, b = 5;
string mathResult = $"Сумма: {a + b}, Разница: {a - b}";
Console.WriteLine(mathResult);


Вывод
Сумма: 15, Разница: 5


🟠Экранирование фигурных скобок
Если нужно вывести {} в тексте, их надо удваивать:
Console.WriteLine($"JSON: {{ \"name\": \"Иван\" }}");


Вывод
JSON: { "name": "Иван" }


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

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


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

HashSet<T> — это коллекция уникальных элементов, которая обеспечивает быстрый поиск, добавление и удаление. В основе HashSet<T> лежит хеш-таблица, что делает операции очень быстрыми (почти за O(1) в среднем случае).

🚩Создание и использование `HashSet<T>`

Простой пример
HashSet<int> numbers = new HashSet<int> { 1, 2, 3, 4, 5 };

// Добавление элементов (дубликаты не добавляются)
numbers.Add(3); // Уже есть в HashSet, не добавится
numbers.Add(6); // Добавится

// Вывод всех элементов
foreach (int num in numbers)
{
Console.Write(num + " ");
}


Вывод
1 2 3 4 5 6


🚩Основные операции

Пример работы с Contains и Remove
if (numbers.Contains(3))
{
numbers.Remove(3);
}

Console.WriteLine(string.Join(", ", numbers));


Вывод
1, 2, 4, 5, 6


🚩Операции над множествами

HashSet<T> поддерживает математические операции над множествами, такие как пересечение, объединение и разность.

Пересечение (IntersectWith)
HashSet<int> set1 = new HashSet<int> { 1, 2, 3, 4 };
HashSet<int> set2 = new HashSet<int> { 3, 4, 5, 6 };

set1.IntersectWith(set2); // Оставит только {3, 4}
Console.WriteLine(string.Join(", ", set1));


Вывод
3, 4


Объединение (UnionWith)
set1 = new HashSet<int> { 1, 2, 3 };
set2 = new HashSet<int> { 3, 4, 5 };

set1.UnionWith(set2); // set1 = {1, 2, 3, 4, 5}
Console.WriteLine(string.Join(", ", set1));


Вывод
1, 2, 3, 4, 5


Разность (ExceptWith)
set1 = new HashSet<int> { 1, 2, 3, 4, 5 };
set2 = new HashSet<int> { 3, 4 };

set1.ExceptWith(set2); // Удалит {3, 4}, останется {1, 2, 5}
Console.WriteLine(string.Join(", ", set1));


Вывод
1, 2, 5


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍72
Forwarded from easyoffer
На easyoffer 2.0 появится:
Тренажер "Реальное собеседование"

🟠 Сценарии вопросов из реального собеседования
🟠Возможность подготовиться к собеседованию в конкретную компанию
🟠Итоговая статистика (прошёл/не прошёл)

Сценарий вопросов взят из реального собеседования. То есть вы тренируетесь на тех вопросах, которые действительно задавались в компании X.

Уже в начале следующей недели стартует краудфандинг кампания, чтобы ускорить разработку easyoffer 2.0. Все кто, поддержал проект на этом этапе смогу получить 1 год доступа к сайту по цене месячной подписки. Первые 150 донатеров получать особо-выгодную цену и бонус. Следите за стартом 👉 в этом телеграм канале, в нем информация о старте будет опубликована за 6 часов до официального начала.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Как происходит кэширование в EF Core?

EF Core использует кэширование на уровне контекста, то есть запрашиваемые сущности хранятся в памяти в пределах одного DbContext. Если та же сущность запрашивается повторно, она возвращается из кэша, а не загружается заново из базы данных. Однако этот кэш существует только в пределах одного экземпляра контекста и не сохраняется между запросами.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4👍2
🤔 Если мы используем 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


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

При сохранении сущности EF Core анализирует все изменения, формирует соответствующие SQL-запросы (например, INSERT, UPDATE или DELETE), отправляет их в базу данных и затем обновляет состояние объектов в памяти, чтобы отразить изменения.


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

Инверсия зависимостей — это принцип 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
👍6
Forwarded from easyoffer
На easyoffer 2.0 появится:
База тестовых заданий

🟠Тестовые задания для разных грейдов
🟠Фильтрация тестовых заданий по технологиям и компаниям

Когда я только начинал учиться на программиста, я постоянно выдумывал себе задачи для практики и тратил на это много времени. Но только в момент поиска работы я столкнулся с тестовыми заданиями, и понял насколько круто они прокачивают навыки. Нужно было еще на этапе обучения пробовать их делать. Все компании стараются составить тестовое задание "под себя", это дает большой выбор в тематике задач и технологий. На easyoffer 2.0 вы сможете отфильтровать тестовые задания по навыкам/грейдам и найти те, что подходят лично вам для практики.

В течение 1-2 дней я объявлю о краудфандинг кампании, чтобы ускорить разработку easyoffer 2.0. Все кто, поддержал проект на этом этапе смогу получить 1 год доступа к сайту по цене месячной подписки и смогут попасть на закрытое бета-тестирование. А первые 150 донатеров получать особо-выгодную цену и бонус.

🚀 Следите за стартом 👉 в этом телеграм канале, в нем информация о старте будет опубликована за 6 часов до официального начала.
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Для чего нужны нереляционные базы данных?

Нереляционные базы данных (NoSQL) используются для работы с большими объёмами данных, структурированных или неструктурированных, а также для обеспечения гибкости и масштабируемости. Они подходят для хранения документов, ключей-значений, графов или временных рядов. Такие базы, как MongoDB или Redis, идеальны для приложений с динамической структурой данных или высокой нагрузкой.

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

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

🟠Примитивные типы (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
🤔 Какие есть положительные и отрицательные моменты у микросервиса?

Положительные:
1. Масштабируемость отдельных компонентов.
2. Независимость разработки и деплоя.
3. Устойчивость: сбой одного микросервиса не влияет на другие.
Отрицательные:
1. Сложность управления распределённой системой.
2. Затраты на сетевые взаимодействия.
3. Сложность обеспечения целостности данных.


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

Паттерн Event Sourcing (событийное моделирование) — это подход к управлению состоянием приложения, при котором все изменения состояния представляются в виде последовательности событий. Вместо хранения текущего состояния объекта в базе данных, сохраняются все изменения состояния (события), которые произошли с этим объектом. Текущее состояние может быть восстановлено путем последовательного применения этих событий.

🚩Основные концепции Event Sourcing:

🟠События (Events): События представляют собой неизменяемые записи фактов, которые произошли в системе. Каждое событие описывает изменение состояния.
🟠Источники событий (Event Stores): Специальные хранилища, которые сохраняют последовательности событий. Они обеспечивают устойчивость событий и возможность их повторного воспроизведения.
🟠Агрегаты (Aggregates): Логические группы объектов, которые обрабатывают команды и генерируют события.
🟠Команды (Commands): Запросы на выполнение изменений, которые обрабатываются агрегатами и приводят к генерации событий.
🟠Проекционные модели (Projections): Модели, создаваемые из последовательностей событий для представления данных в удобной для чтения форме.

🚩Преимущества Event Sourcing:

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

🚩Недостатки Event Sourcing:

🟠Сложность: Реализация Event Sourcing требует дополнительных усилий и знаний.
🟠Объем данных: Хранение всех событий может занимать много места.

public class AccountCreated
{
public Guid AccountId { get; }
public string Owner { get; }

public AccountCreated(Guid accountId, string owner)
{
AccountId = accountId;
Owner = owner;
}
}

public class MoneyDeposited
{
public Guid AccountId { get; }
public decimal Amount { get; }

public MoneyDeposited(Guid accountId, decimal amount)
{
AccountId = accountId;
Amount = amount;
}
}

public class MoneyWithdrawn
{
public Guid AccountId { get; }
public decimal Amount { get; }

public MoneyWithdrawn(Guid accountId, decimal amount)
{
AccountId = accountId;
Amount = amount;
}
}


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