RESTful = соответствующий принципам REST.
Это не технология, а стиль построения API. RESTful API — это API, которое:
- Строится вокруг ресурсов.
- Использует HTTP-методы по назначению.
- Придерживается stateless взаимодействия.
- Предоставляет понятную структуру URL.
- Использует стандартизированные коды ответа.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥3
Делегат (
delegate) — это указатель на метод(ы). Он может хранить: 1. Ссылку на один метод (одиночный делегат)
2. Ссылки на несколько методов (групповой делегат / multicast)
3. Анонимные методы и лямбда-выражения
Делегаты позволяют вызвать метод, даже если его имя заранее неизвестно.
Пример с одиночным делегатом
public delegate void MyDelegate(string message); // Объявляем делегат
public class Program
{
public static void ShowMessage(string msg) => Console.WriteLine($"Сообщение: {msg}");
public static void Main()
{
MyDelegate del = ShowMessage; // Делегат хранит ссылку на метод
del("Привет, делегаты!"); // Вызывает ShowMessage
}
}
Делегаты можно связывать с несколькими методами с помощью
+=. Пример группового делегата public delegate void MyDelegate(string message);
public class Program
{
public static void Method1(string msg) => Console.WriteLine($"Метод 1: {msg}");
public static void Method2(string msg) => Console.WriteLine($"Метод 2: {msg}");
public static void Main()
{
MyDelegate del = Method1;
del += Method2; // Добавляем второй метод
del("Привет!");
// Выведет:
// Метод 1: Привет!
// Метод 2: Привет!
}
}
Делегаты могут хранить "встроенные" методы (без отдельного определения).
Пример с анонимным методом
MyDelegate del = delegate (string msg)
{
Console.WriteLine($"Анонимный метод: {msg}");
};
del("Привет!");
Пример с лямбда-выражением
MyDelegate del = msg => Console.WriteLine($"Лямбда: {msg}");
del("Привет!");Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
1. Finalize (финализатор):
- Позволяет объекту реагировать на удаление.
- Вызывается сборщиком мусора.
- Используется редко, потому что непредсказуем по времени.
2. Dispose:
- Ручной способ освободить управляемые и неуправляемые ресурсы.
- Используется через IDisposable.
- Можно вызывать через конструкцию try-with-resources (using).
3. GC.Collect():
- Принудительно запускает сборку мусора.
- Не рекомендуется использовать без нужды.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7💊2
Методы
FirstOrDefault и SingleOrDefault в LINQ используются для извлечения элементов из коллекции, но их логика работы отличается. Давайте разберем их подробно, с примерами.FirstOrDefault возвращает первый элемент коллекции, который удовлетворяет условию (если условие указано), или первый элемент вообще, если условие отсутствует. Если в коллекции нет элементов, метод возвращает значение по умолчанию для типа (например, null для ссылочных типов или 0 для чисел).Когда вас интересует первый элемент коллекции, но коллекция может быть пустой.
Когда вам неважно, есть ли другие элементы, соответствующие условию.
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
// Возьмем первый элемент, который больше 3
int result = numbers.FirstOrDefault(n => n > 3); // result = 4
// Если условие не выполняется
int result2 = numbers.FirstOrDefault(n => n > 10); // result2 = 0 (default для int)
// Если коллекция пустая
List<int> emptyList = new List<int>();
int result3 = emptyList.FirstOrDefault(); // result3 = 0SingleOrDefault возвращает единственный элемент из коллекции, который удовлетворяет условию. Если такого элемента нет, метод возвращает значение по умолчанию. Однако если в коллекции есть более одного элемента, удовлетворяющего условию, будет выброшено исключение (InvalidOperationException).Когда вы ожидаете, что в коллекции будет ровно один элемент, соответствующий условию.
Когда наличие нескольких подходящих элементов является ошибкой и вы хотите это обработать.
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
// Возьмем единственный элемент, равный 3
int result = numbers.SingleOrDefault(n => n == 3); // result = 3
// Если элемента, соответствующего условию, нет
int result2 = numbers.SingleOrDefault(n => n > 10); // result2 = 0
// Если элементов больше одного, возникает исключение
List<int> duplicateNumbers = new List<int> { 1, 2, 3, 3, 4 };
try
{
int result3 = duplicateNumbers.SingleOrDefault(n => n > 2);
}
catch (InvalidOperationException ex)
{
Console.WriteLine(ex.Message); // Ошибка: последовательность содержит несколько элементов
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
DTO (Data Transfer Object):
- Это простой класс, предназначенный только для передачи данных между слоями (например, между API и сервисом).
- Не содержит логики, только поля и свойства.
- Часто используется:
- при сериализации;
- в REST API;
- для защиты бизнес-модели от утечек наружу.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥1
При выполнении программных задач можно выделить два типа нагрузок:
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
👍2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🤔1
В C# существует множество различных типов данных, которые можно разделить на две основные категории: значимые типы (value types) и ссылочные типы (reference types). Рассмотрим каждую из этих категорий и их подтипы.
Значимые типы хранят данные непосредственно в своей памяти. Они обычно располагаются в стеке и имеют фиксированный размер. К значимым типам относятся:
Числовые типы
Целочисленные типы:
byte (8 бит)sbyte (8 бит)short (16 бит)ushort (16 бит)int (32 бита)uint (32 бита)long (64 бита)ulong (64 бита)Вещественные типы:
float (32 бита)double (64 бита)Десятичный тип:
decimal (128 бит)Логический тип
bool (1 бит, значения true или false)Символьный тип
char (16 бит, символы в формате Unicode)Пользовательские типы, которые могут содержать поля, свойства и методы. Пример:
struct Point { public int X; public int Y; }Специальные типы, представляющие набор именованных констант. Пример:
enum Days { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday }Типы, которые могут принимать значение
null. Пример: int?, double?Основные объекты в C#, могут содержать поля, свойства, методы и события. Пример:
class Person { public string Name; public int Age; }Определяют контракт, который должны реализовать классы. Пример:
interface IMovable { void Move(); }Коллекции однотипных элементов. Пример:
int[] numbers = new int[5];Типы, которые представляют собой ссылки на методы. Пример:
delegate void Process(int value);Непосредственно представляют собой последовательность символов. Пример:
string message = "Hello, World!";Новый тип в C# 9.0, предназначенный для неизменяемых объектов. Пример:
record Person(string Name, int Age);Значимые типы
int a = 5;
float b = 3.14f;
bool isTrue = true;
char letter = 'A';
Ссылочные типы
string message = "Hello, World!";
Person person = new Person { Name = "Alice", Age = 30 };
int[] numbers = new int[] { 1, 2, 3, 4, 5 };
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
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
1👍4
2. Массив: фиксированная структура данных, размер задаётся при создании. Более эффективен в использовании памяти, но менее гибок.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
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
👍3
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3🤔1💊1
Паттерн "Строитель" (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
👍4🤔1
1. Обеспечивает совместимость между этими реализациями, позволяя разрабатывать общий код.
2. Разработчики могут писать библиотеки, работающие на разных версиях и платформах .NET.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
В C# ключ (
TKey) в Dictionary<TKey, TValue> должен быть уникальным и поддерживать сравнение. Лучше всего использовать неизменяемые (
immutable) типы, такие как: Примитивные типы (
int, string, char, bool, Guid, enum) Кортежи (
Tuple, ValueTuple) Неизменяемые структуры (
struct, если переопределён Equals и GetHashCode)Числовые типы (
int, double, long)var dict = new Dictionary<int, string>
{
{1, "Один"},
{2, "Два"}
};
Console.WriteLine(dict[1]); // Вывод: Один
string (лучший выбор)var dict = new Dictionary<string, int>
{
{"apple", 10},
{"banana", 5}
};
Console.WriteLine(dict["apple"]); // 10
Guid (уникальные идентификаторы)var dict = new Dictionary<Guid, string>
{
{Guid.NewGuid(), "User1"},
{Guid.NewGuid(), "User2"}
};
enum (хороший вариант)enum Status { New, Processing, Completed }
var dict = new Dictionary<Status, string>
{
{Status.New, "Заказ создан"},
{Status.Processing, "Заказ в обработке"}
};Можно использовать несколько значений в качестве ключа:
var dict = new Dictionary<(int, string), string>
{
{(1, "apple"), "Красное яблоко"},
{(2, "banana"), "Жёлтый банан"}
};
Console.WriteLine(dict[(1, "apple")]); // Красное яблоко
List<T> (и другие изменяемые коллекции)var dict = new Dictionary<List<int>, string>(); // Ошибка при использовании в качестве ключа!
class, если не переопределён Equals и GetHashCodeclass Person { public string Name; }
var dict = new Dictionary<Person, string>(); // Плохо!Нужно переопределить
Equals и GetHashCodeclass Person
{
public string Name { get; }
public Person(string name) => Name = name;
public override bool Equals(object? obj)
{
return obj is Person other && Name == other.Name;
}
public override int GetHashCode() => Name.GetHashCode();
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3💊1
Плюсы:
- Отложенная инициализация — объект создаётся только при первом обращении.
- Повышение производительности, если объект может не понадобиться вовсе.
- Удобно для дорогостоящих операций или тяжелых зависимостей.
Минусы:
- Может усложнить отладку.
- Необходимость потокобезопасности, особенно при использовании Lazy<T> без параметров.
- Возможные задержки при первом обращении, если инициализация тяжёлая.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Делегаты — это типы, которые безопасно инкапсулируют методы, подобно указателям на функции в других языках программирования, но с проверкой типов во время компиляции. Могут ссылаться на метод, который принимает параметры и возвращает значение. Они используются для реализации обратных вызовов и событий, а также для определения пользовательских операций, которые могут быть выполнены методом, принимаемым в качестве параметра.
Делегаты предоставляют механизм для передачи методов в качестве аргументов другим методам. Это полезно для реализации обратных вызовов, позволяя вызывать методы в ответ на определенные события или условия.
Являются основой системы событий. Они позволяют определять события и подписываться на них. Когда событие происходит, вызываются делегаты, связанные с этим событием, что позволяет реагировать на изменения или действия пользователя.
Позволяют создавать более гибкие и масштабируемые приложения, поскольку методы могут быть переданы и использованы динамически в различных контекстах.
Используются для асинхронного программирования, позволяя выполнять задачи в фоновом режиме, не блокируя основной поток приложения.
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
Это статический метод, который добавляет новую функциональность к существующим классам без их изменения. Это позволяет улучшить читаемость и повторное использование кода.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Forwarded from easyoffer
Напоминаю, что в честь релиза запускаем акцию.
Первые 500 покупателей получат:
🚀 Скидку 50% на PRO тариф на 1 год
🎁 Подарок ценностью 5000₽ для тех, кто подписан на этот канал
🔔 Подпишитесь на этот канал: https://t.iss.one/+b2fZN17A9OQ3ZmJi
В нем мы опубликуем сообщение о релизе в первую очередь
Please open Telegram to view this post
VIEW IN TELEGRAM
В современном C# паттерн Singleton можно реализовать несколькими способами, каждый из которых имеет свои преимущества и предназначен для различных сценариев использования. Рассмотрим несколько распространенных подходов к реализации Singleton.
Ленивый Singleton инициализируется при первом обращении. Это обеспечивает отложенную инициализацию объекта и гарантирует потокобезопасность.
public class Singleton
{
private static readonly Lazy<Singleton> lazyInstance = new Lazy<Singleton>(() => new Singleton());
public static Singleton Instance => lazyInstance.Value;
private Singleton()
{
// Приватный конструктор
}
}
Этот подход использует
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;
}
}
}
Eager Initialization (Инициализация при загрузке)
Экземпляр Singleton создается при загрузке класса. Это гарантирует потокобезопасность за счет особенностей инициализации статических переменных в .NET.
public class Singleton
{
private static readonly Singleton instance = new Singleton();
public static Singleton Instance => instance;
private Singleton()
{
// Приватный конструктор
}
}
Использование статического конструктора для инициализации Singleton.
public class Singleton
{
private static readonly Singleton instance;
static Singleton()
{
instance = new Singleton();
}
public static Singleton Instance => instance;
private Singleton()
{
// Приватный конструктор
}
}
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();
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1