В .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
Если значимый тип (например, int или struct) — это поле класса, то:
- Сам класс хранится в куче (heap).
- Значимый тип как поле будет внутри объекта класса, то есть в той же области памяти (в куче).
Он не уходит в стек отдельно — размещается вместе с объектом, который его содержит.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
Позволяют определять конструкторы прямо в объявлении класса или структуры, что упрощает код и улучшает его читаемость.
public class Person(string name, int age)
{
public string Name { get; } = name;
public int Age { get; } = age;
}
Обеспечивает более удобный синтаксис для создания коллекций.
var numbers = [1, 2, 3, 4, 5];
Теперь можно задавать значения по умолчанию для auto-properties, что делает код более лаконичным.
public string Name { get; set; } = "Unknown";Позволяет использовать алиасы для пространств имен, улучшая читаемость кода.
using Text = System.Text;
Улучшены возможности для работы с лямбда-выражениями, делая их более гибкими и мощными.
Эти нововведения направлены на упрощение синтаксиса языка, улучшение читаемости и поддерживаемости кода, а также на повышение производительности и удобства разработки.
public class Program
{
public static void Main()
{
var person = new Person("John", 30);
Console.WriteLine($"Name: {person.Name}, Age: {person.Age}");
var numbers = [1, 2, 3, 4, 5];
numbers.ForEach(n => Console.WriteLine(n));
var name = new Name { Value = "Unknown" };
Console.WriteLine(name.Value);
}
}
public class Person(string name, int age)
{
public string Name { get; } = name;
public int Age { get; } = age;
}
public class Name
{
public string Value { get; set; } = "Default Name";
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
- Слабая связность — классы не создают зависимости напрямую.
- Тестируемость — можно легко подменить зависимости моками.
- Гибкость — можно менять реализацию без изменения потребителя.
- Расширяемость — можно добавлять новые реализации интерфейсов без изменения старых классов.
- Повторное использование — одно и то же внедрение можно использовать в разных частях системы.
Внедрение зависимостей упрощает архитектуру и повышает удобство поддержки кода.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
IQueryable<T> — это интерфейс, который используется для отложенного выполнения запросов (deferred execution). Он позволяет строить SQL-запросы к базе данных или манипулировать данными в памяти, но сам запрос выполняется только в момент его итерации (ToList(), FirstOrDefault(), Count(), и т. д.).Предположим, у нас есть сущность
Product и контекст базы данных AppDbContextpublic class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
public class AppDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("YourConnectionString");
}
}
Теперь создадим репозиторий, который возвращает
IQueryable<Product>public class ProductRepository
{
private readonly AppDbContext _context;
public ProductRepository(AppDbContext context)
{
_context = context;
}
public IQueryable<Product> GetProducts()
{
return _context.Products.Where(p => p.Price > 100);
// Запрос не выполняется здесь! Только формируется
}
}
Запрос к базе данных выполнится только при материализации (
ToList(), FirstOrDefault(), Count(), и т. д.).var repository = new ProductRepository(new AppDbContext());
// Создаём IQueryable-запрос
IQueryable<Product> query = repository.GetProducts();
// Добавляем дополнительное условие (запрос еще НЕ выполнен)
query = query.OrderBy(p => p.Name);
// Теперь выполняем запрос к БД
List<Product> products = query.ToList(); // SQL-запрос отправляется в базу
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
1. Она позволяет подменять зависимости тестируемого кода фейковыми реализациями.
2. Используется для тестирования изолированных частей приложения без вызова реальных ресурсов.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
В реляционных базах данных связь "один к одному" (one-to-one) подразумевает, что каждая запись в одной таблице соответствует ровно одной записи в другой таблице. Для реализации связи "один к одному" в SQL можно использовать несколько подходов, в зависимости от требований и архитектуры базы данных.
Используйте внешний ключ в одной таблице, который ссылается на первичный ключ другой таблицы, и сделайте этот внешний ключ уникальным.
Используйте один и тот же первичный ключ в обеих таблицах, где одна таблица содержит внешний ключ, который является также первичным ключом.
Таблицы
Users (пользователи)
UserId (Primary Key)
UserName
Profiles (профили)
ProfileId (Primary Key)
UserId (Foreign Key, Unique)
ProfileData
Создание таблиц
CREATE TABLE Users (
UserId INT PRIMARY KEY,
UserName VARCHAR(100)
);
CREATE TABLE Profiles (
ProfileId INT PRIMARY KEY,
UserId INT UNIQUE,
ProfileData VARCHAR(255),
FOREIGN KEY (UserId) REFERENCES Users(UserId)
);
Вставка данных
INSERT INTO Users (UserId, UserName) VALUES (1, 'John Doe');
INSERT INTO Profiles (ProfileId, UserId, ProfileData) VALUES (1, 1, 'Profile data for John Doe');
Запрос данных
SELECT Users.UserName, Profiles.ProfileData
FROM Users
JOIN Profiles ON Users.UserId = Profiles.UserId;
Таблицы
Users (пользователи)
UserId (Primary Key)
UserName
Profiles (профили)
UserId (Primary Key, Foreign Key)
ProfileData
Создание таблиц
CREATE TABLE Users (
UserId INT PRIMARY KEY,
UserName VARCHAR(100)
);
CREATE TABLE Profiles (
UserId INT PRIMARY KEY,
ProfileData VARCHAR(255),
FOREIGN KEY (UserId) REFERENCES Users(UserId)
);
Вставка данных
INSERT INTO Users (UserId, UserName) VALUES (1, 'John Doe');
INSERT INTO Profiles (UserId, ProfileData) VALUES (1, 'Profile data for John Doe');
Запрос данных
SELECT Users.UserName, Profiles.ProfileData
FROM Users
JOIN Profiles ON Users.UserId = Profiles.UserId;
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Slim-версии легче и работают быстрее, но только внутри одного процесса. Они экономичнее по ресурсам и поддерживают асинхронное ожидание. Обычные семафоры — более универсальны, но тяжелее и применимы для взаимодействия между разными процессами.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
В 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
👍1🤔1
ORM (например, Entity Framework) генерирует SQL-запросы на основе LINQ-выражений или методов API.
С точки зрения оптимизации:
- ORM может не всегда создавать эффективные запросы — возможны избыточные JOIN'ы, SELECT * и т.п.
- Хорошие ORM (например, EF Core) стараются оптимизировать SQL, но всё равно могут уступать вручную написанному.
- Можно использовать профайлеры и логирование SQL для контроля и отладки.
- ORM поддерживает отложенное выполнение (IQueryable) и предзагрузку зависимостей (Include), что позволяет управлять оптимизацией вручную.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Dispose метод является частью паттерна управления ресурсами, известного как "Dispose Pattern". Этот метод реализуется в классах через интерфейс
IDisposable. Цель — явное освобождение неуправляемых ресурсов и, по желанию, управляемых ресурсов, прежде чем сборщик мусора освободит объект. Это важно для эффективного управления памятью и другими системными ресурсами.включают в себя ресурсы, которые не управляются средой CLR (Common Language Runtime), например, файловые дескрипторы, сетевые соединения или указатели на память, выделенную вне .NET среды.
это объекты .NET, которые занимают память и потенциально удерживают ссылки на неуправляемые ресурсы.
Должен освобождать все неуправляемые ресурсы, занимаемые объектом, а также должен иметь возможность освобождать управляемые ресурсы, если это необходимо. Как правило, управляемые ресурсы освобождаются сами сборщиком мусора, но если управляемый ресурс включает в себя неуправляемые ресурсы, тогда
Dispose может быть вызван для их явного освобождения.public class ResourceHolder : IDisposable
{
private bool disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Освобождение управляемых ресурсов
}
// Освобождение неуправляемых ресурсов
disposed = true;
}
}
~ResourceHolder()
{
Dispose(false);
}
}
Пример использования Dispose
using (var resource = new ResourceHolder())
{
// Использование ресурса
}
// Метод Dispose автоматически вызывается при выходе из блока using
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊1
В трехслойной архитектуре (трехуровневая архитектура), также известной как многоуровневая архитектура, приложения разделяются на три логических слоя:
Отвечает за взаимодействие с пользователем. Веб-интерфейсы, мобильные приложения, десктопные приложения. Примеры: 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
Число (например, int) — это значимый тип. При передаче копируется значение. Изменения внутри метода не влияют на оригинальную переменную.
Объект (например, экземпляр класса) — это ссылочный тип. Передаётся ссылка, и метод работает с тем же объектом, изменения будут видны снаружи.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥1
Когда браузер отправляет запрос и получает ответ от API, это включает несколько шагов, которые следуют HTTP-протоколу. Этот процесс включает в себя создание и отправку HTTP-запроса, обработку на сервере и получение HTTP-ответа.
Обычно запрос инициируется через JavaScript с использованием встроенных функций, таких как
XMLHttpRequest, fetch или сторонние библиотеки, такие как Axios. fetch('https://api.example.com/data', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token'
}
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
Метод: Указывает тип запроса (например, GET, POST, PUT, DELETE). URL: Указывает на какой URL отправляется запрос. Заголовки (Headers): Включают информацию о типе содержимого, авторизации и других метаданных. Тело (Body): Содержит данные, которые отправляются с запросом (для методов POST, PUT и PATCH).
Браузер использует сетевые протоколы для отправки сформированного HTTP-запроса на указанный сервер через интернет.
Сервер получает HTTP-запрос.
Сервер обрабатывает запрос, выполняя соответствующие действия, такие как чтение данных из базы данных, выполнение логики приложения или взаимодействие с другими сервисами.
Статус код (Status Code): Указывает результат обработки запроса (например, 200 OK, 404 Not Found, 500 Internal Server Error). Заголовки (Headers): Могут включать метаданные о содержимом ответа, кэшировании и других параметрах. Тело (Body): Содержит данные, которые отправляются обратно клиенту, часто в формате JSON или XML.
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 85
{
"id": 1,
"name": "Example",
"description": "This is an example response"
}
Браузер получает HTTP-ответ от сервера.
Статус код: Браузер или JavaScript-код проверяет статус код, чтобы определить, был ли запрос успешным. Заголовки: Заголовки могут быть использованы для получения дополнительной информации о ответе. Тело: Браузер разбирает тело ответа, если это необходимо, например, преобразует JSON-данные в объект JavaScript.
Полученные данные могут быть использованы в приложении для обновления интерфейса пользователя, хранения в локальном хранилище или выполнения других действий.
Отправка запроса
fetch('https://api.example.com/data', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token'
}
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok ' + response.statusText);
}
return response.json();
})
.then(data => {
console.log('Data received:', data);
// Используем данные для обновления UI или других целей
})
.catch(error => {
console.error('There has been a problem with your fetch operation:', error);
});Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
В .NET (и большинстве ООП-языков):
- Функция — подпрограмма, которая возвращает результат.
В C# это — любой static или instance метод с возвращаемым типом.
- Метод — функция, привязанная к классу или объекту.
То есть, в ООП всё называется методами, даже если это технически функция.
Таким образом, всё, что мы называем "функцией" в C#, — это метод. Разница скорее терминологическая.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1
MVVM (Model-View-ViewModel) — это паттерн проектирования, который разделяет логику программы и интерфейс пользователя. Он широко используется в WPF, Xamarin, MAUI и Blazor.
ViewModel обновляет Model (через
Command и INotifyPropertyChanged). Model уведомляет ViewModel об изменениях.
View автоматически обновляется (через Data Binding).
Model (Модель)
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
ViewModel (Логика)
using System.ComponentModel;
using System.Runtime.CompilerServices;
public class PersonViewModel : INotifyPropertyChanged
{
private string _name;
public string Name
{
get => _name;
set { _name = value; OnPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
View (XAML)
<TextBox Text="{Binding Name, Mode=TwoWay}" />
<TextBlock Text="{Binding Name}" />Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3💊1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🔥1
boxing и unboxing — это два важных процесса, связанных с преобразованием типов между значимыми типами (value types) и ссылочными типами (reference types). Эти процессы играют ключевую роль в работе с обобщенными коллекциями и при взаимодействии между различными частями .NET Framework.
Это процесс преобразования переменной значимого типа (например,
int или struct) в тип object или в любой другой тип интерфейса, реализуемый этим значимым типом. При боксинге переменная значимого типа оборачивается в объект ссылочного типа, и её значение копируется в новый объект на управляемой куче. Это необходимо, потому что все элементы в .NET в конечном итоге должны быть объектами.int num = 123;
object obj = num; // Boxing
Это обратный процесс, при котором содержимое объекта ссылочного типа преобразуется обратно в значимый тип. Требует явного указания типа, к которому нужно преобразовать, и может вызывать исключение
InvalidCastException, если объект не может быть преобразован в желаемый значимый тип.object obj = 123; // Boxing
int num = (int)obj; // Unboxing
Боксинг и анбоксинг могут негативно сказаться на производительности, поскольку они влекут за собой операции с памятью, включая выделение памяти и сборку мусора. Поэтому рекомендуется минимизировать их использование, особенно в критичных по производительности частях приложения.
Несмотря на возможное негативное влияние на производительность, боксинг и анбоксинг необходимы для работы со значимыми типами в контекстах, где требуются объекты (например, при работе с коллекциями типа
ArrayList).Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2💊1
try-catch — это механизм обработки исключений в C#.
Код, который может вызвать ошибку во время выполнения, помещается в блок try.
Если ошибка происходит, выполнение переходит в соответствующий блок catch.
Блок finally может использоваться для выполнения завершающих действий, выполняемых независимо от ошибок (например, закрытие файлов, соединений и т.д.).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6💊1
IEnumerable — это интерфейс в базовой библиотеке классов .NET Framework, который определяет один метод:
GetEnumerator(). Этот метод возвращает объект IEnumerator, который позволяет перебирать элементы коллекции (например, массива или списка) один за другим.Используется для создания универсального метода перебора данных, не зависящего от типа коллекции. Это означает, что любой тип данных, который реализует
IEnumerable, можно перебирать с помощью цикла foreach в C#. Это упрощает работу с различными структурами данных, предоставляя единый механизм для итерации элементов.Когда вы реализуете интерфейс
IEnumerable в своём классе, вы обязуете этот класс предоставлять метод GetEnumerator(), который возвращает IEnumerator. IEnumerator, в свою очередь, имеет методы для перехода к следующему элементу (MoveNext) и для получения текущего элемента (Current), а также метод Reset(), который возвращает перечислитель в начальное состояние.using System;
using System.Collections;
public class DaysOfWeek : IEnumerable
{
private string[] days = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
public IEnumerator GetEnumerator()
{
for (int index = 0; index < days.Length; index++)
{
// Yield each day of the week.
yield return days[index];
}
}
}
public class Program
{
public static void Main()
{
DaysOfWeek daysOfWeek = new DaysOfWeek();
foreach (string day in daysOfWeek)
{
Console.WriteLine(day);
}
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3