Dispose и Finalize являются двумя механизмами для управления ресурсами, особенно теми, которые не управляются средой выполнения .NET, такими как файловые дескрипторы или соединения с базой данных. Они играют важную роль в освобождении ресурсов, но работают по-разному.
Можно переопределить в классе для выполнения очистки ресурсов перед тем, как объект будет собран сборщиком мусора. Этот метод вызывается сборщиком мусора автоматически, если объект уничтожается и не имеет других живых ссылок.
Является частью интерфейса
IDisposable и предоставляет явный способ освобождения управляемых и неуправляемых ресурсов. Разработчики могут вызывать Dispose вручную или использовать конструкцию using, которая гарантирует вызов Dispose по завершении блока кода.public class ResourceHolder : IDisposable
{
private bool disposed = false;
~ResourceHolder() // Финализатор
{
Dispose(false);
}
public void Dispose() // Метод Dispose из IDisposable
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Освобождение управляемых ресурсов
}
// Освобождение неуправляемых ресурсов
disposed = true;
}
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ключевое слово using используется в двух основных контекстах: для управления областью видимости объектов, реализующих интерфейс
IDisposable, и для включения пространств имён.Можно использовать для создания блока кода, внутри которого объекты, реализующие интерфейс
IDisposable, автоматически освобождаются по завершении блока. Это удобно для управления ресурсами, такими как файловые потоки, базы данных или другие ресурсы системы, которые требуют явного освобождения.using (StreamWriter writer = new StreamWriter("example.txt"))
{
writer.WriteLine("Hello, world!");
}
// Здесь объект writer уже автоматически закрыт и освобожден.Также используется для объявления пространств имен, которые будут использоваться в коде, позволяя обращаться к классам внутри этих пространств без полного указания их имён.
using System;
using System.IO;
using System.Text;
// Теперь можно использовать классы из System, System.IO и System.Text без полного указания имени.
Для включения статических классов, что позволяет обращаться к статическим членам класса напрямую без указания имени класса.
using static System.Console;
using static System.Math;
class Program
{
static void Main()
{
WriteLine(Sqrt(144)); // Использование метода WriteLine и Sqrt без указания классов Console и Math
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
using — это удобная конструкция, которая автоматически вызывает Dispose, когда объект больше не нужен.
Под капотом она разворачивается в блок с вызовом Dispose в конце, даже если произошла ошибка. Это защищает от утечек ресурсов.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Используются для выполнения логики до и после выполнения метода действия контроллера. Они предоставляют механизм для выполнения кросс-секционных задач, таких как логирование, обработка исключений, валидация и т.д. Action фильтры реализуют интерфейс
IActionFilter или IAsyncActionFilter.Этот метод вызывается перед выполнением метода действия. Здесь можно добавить логику, которая будет выполняться до вызова действия, например, логирование или проверка условий.
public void OnActionExecuting(ActionExecutingContext context)
{
// Логика до выполнения действия
}
Этот метод вызывается после выполнения метода действия. Здесь можно добавить логику, которая будет выполняться после вызова действия, например, логирование результатов или модификация ответа.
public void OnActionExecuted(ActionExecutedContext context)
{
// Логика после выполнения действия
}
Этот метод объединяет функциональность
OnActionExecuting и OnActionExecuted в одном асинхронном методе. Здесь можно определить логику, которая будет выполняться как до, так и после выполнения метода действия.public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
// Логика до выполнения действия
var resultContext = await next();
// Логика после выполнения действия
}
Синхронный Action фильтр:
public class SampleActionFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
// Логика до выполнения действия
Console.WriteLine("Before executing action");
}
public void OnActionExecuted(ActionExecutedContext context)
{
// Логика после выполнения действия
Console.WriteLine("After executing action");
}
}
Асинхронный Action фильтр:
public class SampleAsyncActionFilter : IAsyncActionFilter
{
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
// Логика до выполнения действия
Console.WriteLine("Before executing action");
var resultContext = await next();
// Логика после выполнения действия
Console.WriteLine("After executing action");
}
}
Action фильтр можно применять к контроллерам или действиям контроллера с помощью атрибута
[ServiceFilter] или [TypeFilter]. Также его можно зарегистрировать глобально в Startup.cs.Применение к контроллеру или действию:
[ServiceFilter(typeof(SampleActionFilter))]
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
Глобальная регистрация:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(config =>
{
config.Filters.Add(typeof(SampleActionFilter));
});
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
В 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
Объектно-ориентированное программирование (ООП) основано на четырёх ключевых парадигмах: инкапсуляция, наследование, полиморфизм и абстракция. Оно позволяет строить гибкие и масштабируемые системы. Принципы ООП включают SOLID, GRASP и DRY/KISS/YAGNI.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
HashSet<T> — это коллекция уникальных элементов, которая обеспечивает быстрый поиск, добавление и удаление. В основе HashSet<T> лежит хеш-таблица, что делает операции очень быстрыми (почти за O(1) в среднем случае).Простой пример
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 и Removeif (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
- Обычно значимые типы передаются по значению (создаётся копия).
- Чтобы изменить исходный объект, его передают по ссылке, указав это явно (например, через ref или out).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
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
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍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
1. Передаёт данные в теле запроса, что делает его подходящим для отправки больших или конфиденциальных данных.
2. Используется для операций, которые изменяют состояние сервера, например, создание новых ресурсов.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Блок
using используется для управления временем жизни объектов, которые потребляют неуправляемые ресурсы, такие как файлы, соединения с базой данных или сетевые соединения. Основное преимущество использования блока using заключается в автоматическом освобождении этих ресурсов, что помогает предотвратить утечки ресурсов и улучшить управление памятью.Блок
using гарантирует, что метод Dispose() будет вызван автоматически, когда выполнение кода выйдет из блока using, даже если возникнет исключение. Это освобождает программиста от необходимости вручную вызывать Dispose() и уменьшает вероятность ошибок. using (StreamReader reader = new StreamReader("file.txt"))
{
string content = reader.ReadToEnd();
Console.WriteLine(content);
}
// StreamReader автоматически закрывается и освобождает ресурсы после выхода из блока using. Использование блока
using уменьшает количество необходимого кода для обеспечения правильного освобождения ресурсов. using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
// Работа с базой данных
}
// SqlConnection автоматически закрывается и освобождает ресурсы после выхода из блока using.
Блок
using повышает надежность кода, так как гарантирует, что ресурсы будут освобождены даже в случае возникновения исключений. try
{
using (StreamWriter writer = new StreamWriter("file.txt"))
{
writer.WriteLine("Hello, World!");
}
}
catch (Exception ex)
{
Console.WriteLine($"Произошла ошибка: {ex.Message}");
}
// StreamWriter автоматически закрывается и освобождает ресурсы после выхода из блока using, даже если произошла ошибка.
Код, использующий блок
using, выглядит более чистым и упрощает понимание и сопровождение. using (MemoryStream memoryStream = new MemoryStream())
{
// Работа с MemoryStream
}
// MemoryStream автоматически освобождается после выхода из блока using.
Работа с файлами
using System;
using System.IO;
class Program
{
static void Main()
{
using (StreamReader reader = new StreamReader("example.txt"))
{
string content = reader.ReadToEnd();
Console.WriteLine(content);
}
// StreamReader автоматически закрывается и освобождает ресурсы после выхода из блока using.
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Используется CancellationToken:
1. Создаётся CancellationTokenSource.
2. В метод передаётся токен.
3. При отмене — токен сигнализирует завершение задачи.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥1
Метод
set в контексте чаще всего используется в свойствах (properties) класса и служит для установки значения свойства. Он работает как часть автоматического или пользовательского свойства, позволяя контролировать, что происходит, когда свойству присваивается значение. Свойство (property) в C# – это синтаксический сахар, который позволяет обращаться к полям класса как к переменным, но при этом добавляет возможность добавлять логику для получения (
get) и установки (set) значений.public class Person
{
private string name; // Закрытое поле
public string Name // Свойство
{
get { return name; } // Получить значение
set { name = value; } // Установить значение
}
}
Например, вы можете ограничить, какие значения можно присваивать.
Например, логирование или обновление других полей.
Вы можете использовать метод
set для проверки значений на валидность или ограничения доступа (например, сделать его приватным).Проверка входных данных:
public class Person
{
private int age;
public int Age
{
get { return age; }
set
{
if (value < 0)
{
throw new ArgumentException("Возраст не может быть отрицательным.");
}
age = value;
}
}
}
Только для чтения
Вы можете сделать
set приватным, чтобы свойство можно было только читать извне:public class Person
{
public string Name { get; private set; }
public Person(string name)
{
Name = name;
}
}
Автоматические свойства
Если вам не нужна дополнительная логика, можно использовать автоматические свойства
public class Person
{
public string Name { get; set; } // Автоматически создаются get и set
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1💊1
Нулевое поколение (Generation 0) — это область памяти, куда помещаются все новые объекты, когда они только создаются.
Туда попадают:
- Все новые экземпляры классов.
- Краткоживущие объекты (например, временные строки, коллекции и т.п.).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🔥1
Semaphore – классический семафор, использующий ядро операционной системы для синхронизации потоков. SemaphoreSlim – более лёгкая и быстрая версия, работающая в основном на уровне управляемого кода без вызовов ядра ОС. Используйте
Semaphore, если: Вам нужно разделение ресурсов между разными процессами.
Вы работаете с нативным кодом или сторонними API, использующими семафоры ОС.
Используйте
SemaphoreSlim, если: Вам нужна быстрая блокировка между потоками в одном процессе.
Вы хотите использовать асинхронный код (
async/await). Вам важна производительность.
using System;
using System.Threading;
class Program
{
static Semaphore semaphore = new Semaphore(2, 2); // Макс. 2 потока могут войти одновременно
static void Main()
{
for (int i = 1; i <= 5; i++)
{
new Thread(DoWork).Start(i);
}
}
static void DoWork(object id)
{
Console.WriteLine($"Поток {id} ждёт семафор...");
semaphore.WaitOne(); // Захватываем семафор
Console.WriteLine($"Поток {id} выполняет работу...");
Thread.Sleep(2000); // Симуляция работы
Console.WriteLine($"Поток {id} освобождает семафор");
semaphore.Release(); // Освобождаем семафор
}
}
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(2); // 2 потока одновременно
static async Task Main()
{
Task[] tasks = new Task[5];
for (int i = 0; i < 5; i++)
{
tasks[i] = DoWork(i);
}
await Task.WhenAll(tasks);
}
static async Task DoWork(int id)
{
Console.WriteLine($"Задача {id} ждёт семафор...");
await semaphoreSlim.WaitAsync(); // Асинхронное ожидание
Console.WriteLine($"Задача {id} выполняет работу...");
await Task.Delay(2000); // Симуляция работы
Console.WriteLine($"Задача {id} освобождает семафор");
semaphoreSlim.Release(); // Освобождаем семафор
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ключи должны быть:
- Уникальными
- Иметь устойчивую реализацию GetHashCode() и Equals()
Подходящие типы:
- Примитивы (int, string, GUID и т.п.)
- Структуры (например, кастомные value types)
- Объекты (если правильно переопределены Equals и GetHashCode)
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
Да, порядок
catch имеет значение! Исключения проверяются сверху вниз, и первый подходящий
catch будет выполнен. 1. Исключение проверяется по порядку
catch-блоков. 2. Если
catch подходит → он выполняется, остальные игнорируются. 3. Специфичные исключения (
DivideByZeroException) нужно ставить выше общих (Exception). Так делать нельзя!
try
{
int x = 5 / 0; // Ошибка
}
catch (Exception ex) // Ловит все исключения
{
Console.WriteLine("Общая ошибка");
}
catch (DivideByZeroException ex) // Никогда не выполнится!
{
Console.WriteLine("Деление на ноль!");
}
Правильный порядок
catchtry
{
int x = 5 / 0;
}
catch (DivideByZeroException ex) // Специфичный `catch` первым
{
Console.WriteLine("Ошибка: деление на ноль!");
}
catch (Exception ex) // Общий `catch` внизу
{
Console.WriteLine("Произошла ошибка!");
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1