Сравнение значений переменных может зависеть от типа данных, хранящихся в этих переменных, и от способа их сравнения.
Для примитивных типов (например,
int, float, char, bool) значение хранятся непосредственно в переменных, и их сравнение выполняется по значению. int a = 5;
int b = 5;
bool areEqual = (a == b); // True
Для ссылочных типов (например, классы, строки) переменные содержат ссылки на объекты в куче. Сравнение ссылочных типов по умолчанию выполняется по ссылке, а не по значению.
class Person
{
public string Name { get; set; }
}
Person person1 = new Person { Name = "Alice" };
Person person2 = new Person { Name = "Alice" };
bool areEqual = (person1 == person2); // False, потому что сравниваются ссылки
Строки являются ссылочными типами, но переопределяют операторы сравнения
== и 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
Транзакция — это единица работы с базой данных, которая выполняется полностью или не выполняется вовсе. Основные свойства транзакции — ACID:
- Atomicity (атомарность) — всё или ничего.
- Consistency (согласованность) — данные переходят из одного допустимого состояния в другое.
- Isolation (изолированность) — параллельные транзакции не мешают друг другу.
- Durability (надёжность) — после коммита изменения сохраняются.
В .NET можно управлять транзакциями вручную или через TransactionScope.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊2🔥1
Это небольшие фрагменты данных, которые веб-сайты сохраняют на устройствах пользователей для хранения информации о сессии и отслеживания состояния. Куки используются для различных целей, таких как аутентификация пользователей, хранение настроек и предпочтений, а также отслеживание активности пользователей на сайте.
Уникальный идентификатор для каждого куки.
Данные, которые хранит куки.
Домен, для которого куки действителен.
Путь на сервере, для которого куки действителен.
Дата или время, когда куки должен быть удален.
Указывает, что куки должны передаваться только через HTTPS.
Указывает, что куки недоступен через JavaScript, только через HTTP(S) запросы.
Сервер отправляет куки в ответе на запрос клиента с использованием заголовка
Set-Cookie. HTTP/1.1 200 OK
Set-Cookie: sessionId=abc123; Path=/; Expires=Wed, 09 Jun 2023 10:18:14 GMT
Content-Type: text/html
Браузер автоматически добавляет соответствующие куки в заголовок
Cookie при каждом последующем запросе к серверу, для которого эти куки действительны. GET /dashboard HTTP/1.1
Host: example.com
Cookie: sessionId=abc123
Установка куки на сервере (пример на Node.js с использованием Express)
const express = require('express');
const app = express();
app.get('/', (req, res) => {
// Устанавливаем куки
res.cookie('sessionId', 'abc123', {
maxAge: 900000,
httpOnly: true
});
res.send('Куки установлены');
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});Доступ к куки на клиенте (пример на JavaScript)
// Установка куки
document.cookie = "username=JohnDoe; expires=Thu, 18 Dec 2023 12:00:00 UTC; path=/";
// Получение всех куки
let cookies = document.cookie;
console.log(cookies);
Куки с флагом
Secure передаются только по HTTPS-соединениям. Куки с флагом HttpOnly недоступны через JavaScript, что помогает защитить их от XSS-атак.Обычно один куки не должен превышать 4KB, и на одном домене может быть установлено не более 20-30 куки.
Куки могут содержать чувствительные данные, поэтому важно защищать их и использовать шифрование, если необходимо.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Абстрактная фабрика — это паттерн, который позволяет создавать семейства взаимосвязанных объектов, не привязываясь к конкретным классам.
Пример:
В графической системе можно иметь:
- Button и Checkbox для Windows,
- Button и Checkbox для macOS.
Абстрактная фабрика позволяет создавать соответствующие элементы без знания, для какой платформы они реализованы.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Forwarded from easyoffer
Новая фича на easyoffer – Автоотлики
Вы автоматически откликаетесь на подходящие вам вакансии. Попробуйте её бесплатно и начните получать больше предложений о работе.
🚀 Запуск занимаем всего 3 минуты, а экономит очень много времени
🛡 Это безопасно: easyoffer официально одобрен HeadHunter и прошел его модерацию.
🥷🏻 Автоотклик незаметен для рекртера. Автоотклик ничем не отличается от обычного отклика, который вы делаете вручную
Рекрутеры давно используют автоматизацию для поиска кандидатов. Так почему вы должны откликаться вручную?
💡Совет – Добавьте шаблон сопроводительного письма, чтобы откликаться на большее количество вакансий (на некоторые вакансии нельзя откликнуться без сопроводительного)
Попробовать бесплатно → https://easyoffer.ru/autoapply
Вы автоматически откликаетесь на подходящие вам вакансии. Попробуйте её бесплатно и начните получать больше предложений о работе.
🚀 Запуск занимаем всего 3 минуты, а экономит очень много времени
🛡 Это безопасно: easyoffer официально одобрен HeadHunter и прошел его модерацию.
🥷🏻 Автоотклик незаметен для рекртера. Автоотклик ничем не отличается от обычного отклика, который вы делаете вручную
Рекрутеры давно используют автоматизацию для поиска кандидатов. Так почему вы должны откликаться вручную?
💡Совет – Добавьте шаблон сопроводительного письма, чтобы откликаться на большее количество вакансий (на некоторые вакансии нельзя откликнуться без сопроводительного)
Попробовать бесплатно → https://easyoffer.ru/autoapply
В .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