Value Type (тип значения) – это тип данных, который хранит своё значение непосредственно в памяти (обычно в стеке), а не ссылку на объект в куче (heap), как это делает ссылочный тип (Reference Type).
Простые типы (
int, double, bool, char, byte, float, decimal, etc.) Структуры (
struct) Перечисления (
enum) Nullable-значения (
int?, double?) int a = 10;
int b = a; // Значение копируется
b = 20;
Console.WriteLine(a); // 10 (остался неизменным)
Console.WriteLine(b); // 20
Value Type обычно хранятся в стеке (stack) – это быстрая область памяти.
Если структура (
struct) является частью объекта (который хранится в куче), то её значение хранится внутри объекта в куче. struct Point
{
public int X;
public int Y;
}
class Program
{
static void Main()
{
Point p1 = new Point { X = 5, Y = 10 };
Point p2 = p1; // Копирование структуры (создаётся новый экземпляр)
p2.X = 20;
Console.WriteLine(p1.X); // 5 (остался неизменным)
Console.WriteLine(p2.X); // 20
}
}
Если данные небольшие и часто изменяются –
struct Если объект недолговечный и не требует сложного поведения
Если производительность важна – Value Type быстрее из-за работы в стеке
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🤔1
Оператор
new в C# создаёт новый экземпляр объекта и выделяет для него память в куче (Heap) или стеке (Stack), в зависимости от типа. Для классов (
class) – выделяет память в куче (Heap) и возвращает ссылку на объект. Для структур (
struct) – если структура создаётся без new, её поля остаются неинициализированными, но если использовать new, она получает значения по умолчанию. Для массивов (
T[]) – выделяет память в куче, даже если T – это struct. Для делегатов – создаёт экземпляр делегата.
Пример:
new с классом (class)class Person
{
public string Name;
public Person(string name)
{
Name = name;
}
}
class Program
{
static void Main()
{
Person p1 = new Person("Alice"); // Создаём новый объект в куче
Console.WriteLine(p1.Name); // Alice
}
}
Пример:
new со структурой (struct)struct Point
{
public int X;
public int Y;
public Point(int x, int y)
{
X = x;
Y = y;
}
}
class Program
{
static void Main()
{
Point p1 = new Point(5, 10); // Создаёт структуру в стеке
Console.WriteLine(p1.X); // 5
}
}
Пример:
new с массивомint[] numbers = new int[5]; // Создаёт массив в куче
numbers[0] = 10;
Console.WriteLine(numbers[0]); // 10
Выделение памяти в куче (для классов) или в стеке (для структур).
Вызов конструктора класса или структуры.
Возвращение ссылки на объект (для классов) или самого объекта (для структур).
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Связь «многие ко многим» требует создания промежуточной таблицы, которая содержит пары идентификаторов связанных объектов. В объектно-ориентированном программировании используются коллекции объектов, хранящие ссылки друг на друга, что обеспечивает гибкость взаимодействия.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Dependency Injection (DI) — это паттерн проектирования, который помогает управлять зависимостями в приложении, делая код более гибким, тестируемым и поддерживаемым. Библиотека DI предоставляет механизмы для внедрения зависимостей автоматически, без явного создания экземпляров объектов в коде.
Без DI мы часто создаем объекты внутри классов вручную, что приводит к жесткой связности (tight coupling). Это делает код менее гибким и сложным в тестировании. DI помогает:
Разделить зависимости: объекты получают зависимости извне, а не создают их самостоятельно.
Облегчить тестирование: можно подставлять мок-объекты вместо реальных зависимостей.
Сделать код более гибким: легко подменять реализации зависимостей.
В .NET Core и .NET 5+ встроена своя Microsoft.Extensions.DependencyInjection, но можно использовать сторонние библиотеки, такие как Autofac, Ninject, Unity.
Регистрация зависимостей
Внедрение зависимостей
Жизненный цикл зависимостей
Создадим интерфейс и его реализацию
public interface IMessageService
{
void SendMessage(string message);
}
public class EmailService : IMessageService
{
public void SendMessage(string message)
{
Console.WriteLine($"Отправка Email: {message}");
}
}
Зарегистрируем зависимость в DI-контейнере
var serviceProvider = new ServiceCollection()
.AddSingleton<IMessageService, EmailService>()
.BuildServiceProvider();
Получим зависимость через DI
var messageService = serviceProvider.GetService<IMessageService>();
messageService.SendMessage("Привет, DI!");
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1
Связь «один к одному» подразумевает, что у каждой записи есть только одна связанная запись в другой таблице. Связь «многие ко многим» позволяет одной записи соответствовать множеству записей в другой таблице, требуя дополнительного слоя связи через промежуточную сущность.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
В C# есть две похожие коллекции:
ArrayList(старый подход) и List<T> (современный вариант). Основные отличия: ArrayList arrayList = new ArrayList();
arrayList.Add(1);
arrayList.Add("Hello"); // Ошибки возможны при приведении типов
List<int> list = new List<int>();
list.Add(1); // Только int, безопаснее
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8👾4
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4
В C# все типы делятся на значимые (value types) и ссылочные (reference types). Основное различие заключается в том, как данные хранятся в памяти и как передаются в методы.
Хранятся в стеке (Stack).
Передаются по значению (копируются).
Каждый объект имеет свою копию данных.
Не могут быть
null (если не использовать Nullable<T>). -
int, double, bool, char -
struct, enum, DateTime int a = 10;
int b = a; // Копия значения
b = 20;
Console.WriteLine(a); // 10 (не изменился)
Console.WriteLine(b); // 20
Хранятся в куче (Heap), а в стеке лежит ссылка на объект.
Передаются по ссылке (не копируются, а передаётся адрес).
Несколько переменных могут указывать на один и тот же объект.
Могут быть
null (если не инициализированы). class Person
{
public string Name;
}
Person p1 = new Person { Name = "Alice" };
Person p2 = p1; // p2 и p1 указывают на один объект
p2.Name = "Bob";
Console.WriteLine(p1.Name); // Bob (изменилось!)
Console.WriteLine(p2.Name); // Bob
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
😁9🔥4👍3🤯1👾1
Абстрактный класс и интерфейс - это два механизма, которые обеспечивают наследование и полиморфизм, но они используются по-разному и для разных целей.
Представляет собой класс, от которого нельзя создать экземпляр напрямую. Он предназначен для описания общего поведения и состояния своих подклассов. Абстрактные классы могут содержать реализацию некоторых методов и свойств. Это означает, что абстрактный класс может содержать как абстрактные методы (без реализации), так и методы с реализацией. Подклассы абстрактного класса обязаны реализовать все абстрактные методы, но они также наследуют реализованные методы и свойства.
public abstract class Животное
{
public abstract void Есть(); // Абстрактный метод, должен быть реализован в наследнике.
public void Дышать() // Метод с реализацией, наследуется всеми наследниками.
{
Console.WriteLine("Дыхание");
}
}
Интерфейс определяет контракт, который классы или структуры могут реализовывать. Интерфейсы могут содержать объявления методов, свойств, событий, но не их реализации. Класс или структура, реализующие интерфейс, должны предоставить реализацию для всех его членов. Важно отметить, что класс может реализовывать несколько интерфейсов, что обеспечивает форму множественного наследования.
public interface IЖивотное
{
void Есть(); // Метод, который должен быть реализован в классе.
}
Класс может наследовать только от одного абстрактного класса (из-за ограничения одиночного наследования в C#), но может реализовывать множество интерфейсов.
Абстрактные классы могут содержать реализацию методов и поля данных, в то время как интерфейсы могут содержать только объявления методов и свойств (без полей и реализации).
Абстрактные классы могут иметь конструкторы и деструкторы, в то время как интерфейсы - нет.
В интерфейсах все члены по умолчанию являются public, и вы не можете указать другой модификатор доступа. В абстрактных классах вы можете использовать различные модификаторы доступа.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔5❤2👍2😁2👾1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
Делегаты — это типы, которые безопасно инкапсулируют методы, подобно указателям на функции в других языках программирования, но с проверкой типов во время компиляции. Могут ссылаться на метод, который принимает параметры и возвращает значение. Они используются для реализации обратных вызовов и событий, а также для определения пользовательских операций, которые могут быть выполнены методом, принимаемым в качестве параметра.
Делегаты предоставляют механизм для передачи методов в качестве аргументов другим методам. Это полезно для реализации обратных вызовов, позволяя вызывать методы в ответ на определенные события или условия.
Являются основой системы событий. Они позволяют определять события и подписываться на них. Когда событие происходит, вызываются делегаты, связанные с этим событием, что позволяет реагировать на изменения или действия пользователя.
Позволяют создавать более гибкие и масштабируемые приложения, поскольку методы могут быть переданы и использованы динамически в различных контекстах.
Используются для асинхронного программирования, позволяя выполнять задачи в фоновом режиме, не блокируя основной поток приложения.
public delegate int Operation(int x, int y);
public class Calculator
{
public int PerformOperation(int x, int y, Operation op)
{
return op(x, y);
}
}
class Program
{
static int Add(int x, int y)
{
return x + y;
}
static int Multiply(int x, int y)
{
return x * y;
}
static void Main()
{
Calculator calc = new Calculator();
// Создание делегата для метода Add и вызов через метод PerformOperation
Operation addOp = new Operation(Add);
int result = calc.PerformOperation(5, 6, addOp);
Console.WriteLine("Addition: " + result);
// Создание делегата для метода Multiply и вызов через метод PerformOperation
Operation mulOp = new Operation(Multiply);
result = calc.PerformOperation(5, 6, mulOp);
Console.WriteLine("Multiplication: " + result);
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Жизненные циклы объектов управляют временем их существования в зависимости от контекста. Это важно для оптимизации работы с памятью и управляемого уничтожения ресурсов. В средах с зависимостями, таких как DI-контейнеры или фреймворки, они определяют, когда объект должен быть создан и уничтожен.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
В трехслойной архитектуре (трехуровневая архитектура), также известной как многоуровневая архитектура, приложения разделяются на три логических слоя:
Отвечает за взаимодействие с пользователем. Веб-интерфейсы, мобильные приложения, десктопные приложения. Примеры: HTML/CSS/JavaScript для веб-приложений, UI-компоненты в мобильных и десктопных приложениях.
Содержит бизнес-логику и правила приложения. Обрабатывает данные, выполняет вычисления, применяет бизнес-правила. Примеры: классы и методы, реализующие бизнес-логику, сервисы, обработчики данных.
Отвечает за взаимодействие с источниками данных. Операции с базами данных, файловыми системами, внешними сервисами. Примеры: репозитории, Data Access Objects (DAO), API-клиенты для доступа к внешним системам.
REST — это архитектурный стиль для разработки веб-сервисов. RESTful сервисы используют стандартные HTTP методы (GET, POST, PUT, DELETE и т.д.) для работы с ресурсами.
С точки зрения трехслойной архитектуры:
Презентационный слой:
Вызовы REST API могут происходить с клиентской стороны (например, AJAX запросы из веб-интерфейса) или через клиентские приложения.
Пример: фронтенд веб-приложения, который взаимодействует с REST API.
Логический слой:
REST API реализует бизнес-логику и выступает посредником между презентационным слоем и слоем данных.
Пример: контроллеры и сервисы, обрабатывающие REST запросы и выполняющие соответствующую бизнес-логику.
Слой данных:
REST API может взаимодействовать с базой данных или другими источниками данных для получения и сохранения информации.
Пример: методы в API, которые выполняют запросы к базе данных через репозитории или DAO.
SWAP — это гипотетический или менее распространенный термин, часто интерпретируемый как упрощенный API для веб-приложений.
Презентационный слой
Клиентские приложения или пользовательские интерфейсы могут вызывать методы SWAP для получения или отправки данных.Пример: веб-страницы или мобильные приложения, обращающиеся к SWAP для выполнения операций.
Логический слой:
SWAP обрабатывает бизнес-логику аналогично REST API, предоставляя упрощенные конечные точки для взаимодействия с данными.
Пример: сервисы, которые реализуют простые операции (CRUD) без сложной бизнес-логики.
Слой данных:
SWAP взаимодействует с базой данных или другими источниками данных для выполнения операций чтения/записи.
Пример: методы SWAP, которые обращаются к базе данных через абстрактные уровни доступа к данным.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
REST основывается на принципах клиент-серверной архитектуры, статeless-состояний и унифицированного интерфейса. Запросы к API должны быть идемпотентными, использовать стандартизированные методы, а ресурсы должны быть представлены через понятные URL-адреса.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥2
При выполнении программных задач можно выделить два типа нагрузок:
I/O-bound (ограничение ввода-вывода)
CPU-bound (ограничение процессора)
Основная проблема: программа ждет завершения операций ввода-вывода (диска, сети, базы данных, файловой системы и т. д.), а не загружает процессор.
Примеры:
- Чтение и запись файлов на диск
- Запросы к базе данных
- HTTP-запросы к API
- Чтение данных из сети
Решение: Использование асинхронного программирования (
async/await), чтобы не блокировать поток. public async Task<string> FetchDataAsync()
{
using HttpClient client = new HttpClient();
return await client.GetStringAsync("https://example.com");
}
Основная проблема: процессор сильно загружен вычислениями, и узким местом становится скорость обработки данных, а не ввод-вывод.
Примеры:
- Генерация больших отчетов
- Кодирование/декодирование видео
- Комплексные математические вычисления
- Сортировка больших массивов
public static long CalculateFactorial(int number)
{
return Enumerable.Range(1, number).Aggregate(1, (a, b) => a * b);
}
public async Task<long> ComputeAsync(int number)
{
return await Task.Run(() => CalculateFactorial(number));
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3
Это процесс подтверждения подлинности пользователя или системы, предоставляющего доступ к ресурсу. Она проверяет соответствие введенных учетных данных зарегистрированному пользователю и может использовать различные механизмы защиты.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Исключения в программировании — это механизмы обработки ошибок и необычных ситуаций, которые возникают во время выполнения программы. В C# и других языках программирования исключения позволяют отделить код обработки ошибок от основного кода программы, что упрощает его чтение и поддержку.
Событие, которое прерывает нормальный поток выполнения программы.
Содержит код, который может вызвать исключение.
Содержит код, который выполняется, если возникает исключение. В catch блок можно передать параметр — экземпляр исключения, которое произошло.
Содержит код, который выполняется в любом случае, независимо от того, произошло исключение или нет. Обычно используется для освобождения ресурсов.
Механизм для явного вызова исключения.
Основные блоки
try
{
// Код, который может вызвать исключение
int divisor = 0;
int result = 10 / divisor;
}
catch (DivideByZeroException ex)
{
// Обработка исключения
Console.WriteLine("Деление на ноль невозможно.");
}
finally
{
// Код, который выполнится в любом случае
Console.WriteLine("Блок finally выполнен.");
}
Создание и бросание собственного исключения
public class InvalidAgeException : Exception
{
public InvalidAgeException(string message) : base(message) { }
}
public void SetAge(int age)
{
if (age < 0)
{
throw new InvalidAgeException("Возраст не может быть отрицательным.");
}
// Логика установки возраста
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🤯1
Существует несколько типов аутентификации, включая базовую аутентификацию по логину и паролю, одноразовые коды, токены (OAuth, JWT) и биометрические методы. Выбор зависит от уровня безопасности и удобства для пользователя.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🤔2