Значимые типы обычно хранятся в стеке, так как их память выделяется статически. Если значимый тип является частью ссылочного типа, он будет храниться в куче.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥4
1. Используйте обобщения (Generics), которые позволяют работать с типами без преобразования.
2. Применяйте значимые типы вместо ссылочных, где это возможно.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
1. Неизменяемость:
- После создания строка не может быть изменена.
2. Ссылочный тип:
- Хотя String является ссылочным типом, его ведение в памяти ближе к значимым, так как неизменяемость обеспечивает предсказуемость поведения.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4😁1
Выбор между интерфейсом и абстрактным классом в C# зависит от нескольких факторов, таких как потребности в наследовании, степень общности, возможность множественного наследования и необходимость реализации по умолчанию.
Класс может реализовывать несколько интерфейсов, но наследоваться только от одного класса. Используйте интерфейсы, когда требуется множественное наследование.
public interface IDriveable
{
void Drive();
}
public interface IFlyable
{
void Fly();
}
public class FlyingCar : IDriveable, IFlyable
{
public void Drive() { /* Реализация вождения */ }
public void Fly() { /* Реализация полета */ }
}
Используйте интерфейсы, чтобы определить общий набор методов и свойств без предоставления какой-либо реализации. Это позволяет разным классам реализовать интерфейс по-своему.
public interface IShape
{
double GetArea();
}
public class Circle : IShape
{
public double Radius { get; set; }
public double GetArea() => Math.PI * Radius * Radius;
}
public class Rectangle : IShape
{
public double Width { get; set; }
public double Height { get; set; }
public double GetArea() => Width * Height;
}
Интерфейсы позволяют легко менять реализацию и обеспечивают гибкость в коде. Можно использовать интерфейсы для создания полиморфных коллекций или методов, которые работают с разными реализациями интерфейсов.
public void DrawShapes(IEnumerable<IShape> shapes)
{
foreach (var shape in shapes)
{
Console.WriteLine($"Area: {shape.GetArea()}");
}
}
Используйте абстрактные классы, если вы хотите предоставить некоторую общую реализацию, которую могут использовать подклассы. Абстрактные классы могут содержать как абстрактные, так и не абстрактные методы.
public abstract class Animal
{
public abstract void MakeSound();
public void Sleep() => Console.WriteLine("Sleeping");
}
public class Dog : Animal
{
public override void MakeSound() => Console.WriteLine("Bark");
}
Абстрактные классы хорошо подходят для реализации паттерна "Шаблонный метод", где общий алгоритм реализован в абстрактном классе, а конкретные шаги определены в подклассах.
public abstract class Game
{
public void Play()
{
Initialize();
StartPlay();
EndPlay();
}
protected abstract void Initialize();
protected abstract void StartPlay();
protected abstract void EndPlay();
}
public class Football : Game
{
protected override void Initialize() => Console.WriteLine("Football Game Initialized");
protected override void StartPlay() => Console.WriteLine("Football Game Started");
protected override void EndPlay() => Console.WriteLine("Football Game Ended");
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥1
Interceptor (перехватчик) — это паттерн программирования, используемый для перехвата и обработки вызовов методов, запросов или событий перед их исполнением или после. В контексте C# и .NET, интерцепторы чаще всего применяются в:
ASP.NET Core Middleware — для перехвата HTTP-запросов.
Entity Framework Core Interceptors — для перехвата SQL-запросов и изменений данных.
Aspect-Oriented Programming (AOP) — для добавления кода перед или после выполнения метода.
можно записывать запросы, исключения, время выполнения.
проверка прав доступа перед выполнением запроса.
автоматическое управление транзакциями в базе данных.
например, автоматическая подмена аргументов.
можно сохранять результаты выполнения метода.
Entity Framework Core позволяет использовать интерцепторы для перехвата SQL-запросов. Это может быть полезно, например, для логирования всех SQL-запросов.
using Microsoft.EntityFrameworkCore.Diagnostics;
using System;
using System.Data.Common;
using System.Threading;
using System.Threading.Tasks;
public class SqlInterceptor : DbCommandInterceptor
{
public override InterceptionResult<DbDataReader> ReaderExecuting(
DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result)
{
Console.WriteLine($"SQL Query: {command.CommandText}");
return base.ReaderExecuting(command, eventData, result);
}
}
Теперь подключим этот интерцептор в DbContext
using Microsoft.EntityFrameworkCore;
public class MyDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.AddInterceptors(new SqlInterceptor());
base.OnConfiguring(optionsBuilder);
}
}
В ASP.NET Core интерцепторы можно реализовать через Middleware. Например, перехватим все HTTP-запросы и добавим в лог
public class RequestInterceptor
{
private readonly RequestDelegate _next;
public RequestInterceptor(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
Console.WriteLine($"HTTP Request: {context.Request.iss.onethod} {context.Request.Path}");
await _next(context);
}
}
Добавляем middleware в
Program.csvar builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseMiddleware<RequestInterceptor>();
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
app.Run();
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
ThreadPool (пул потоков) — это механизм управления потоками в .NET, который позволяет повторно использовать созданные потоки для выполнения задач, уменьшая накладные расходы на их создание и уничтожение.
Каждый раз создавать новый поток — медленно и неэффективно.
вместо их постоянного создания и удаления.
в зависимости от нагрузки.
Обработки HTTP-запросов
Выполнения задач в фоне
Асинхронного выполнения операций
он берет поток из пула и выполняет задачу.
создается новый (но их количество ограничено).
а возвращается в пул и может быть использован снова.
в зависимости от загрузки системы.
using System;
using System.Threading;
class Program
{
static void Main()
{
for (int i = 0; i < 5; i++)
{
ThreadPool.QueueUserWorkItem(DoWork, i);
}
Console.ReadLine(); // Ждём завершения потоков
}
static void DoWork(object? state)
{
Console.WriteLine($"Задача {state} выполняется в потоке {Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(1000); // Симуляция работы
Console.WriteLine($"Задача {state} завершена");
}
}
ThreadPool управляет количеством потоков сам, но их можно настраивать
int minWorker, minIOC;
ThreadPool.GetMinThreads(out minWorker, out minIOC);
Console.WriteLine($"Мин. количество потоков: {minWorker}");
ThreadPool.SetMinThreads(4, 4); // Устанавливаем минимум потоков
int maxWorker, maxIOC;
ThreadPool.GetMaxThreads(out maxWorker, out maxIOC);
Console.WriteLine($"Макс. количество потоков: {maxWorker}");
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥2
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
👍5
- Semaphore позволяет нескольким потокам одновременно получить доступ к ресурсу, если это допускается заданным лимитом (например, 3 потока). Mutex используется для синхронизации одного ресурса, а Semaphore — для ограничения доступа к нескольким потокам.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍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
🤯1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥1
Extension-методы (методы расширения) — это способ добавить новые методы к существующим классам, не изменяя их код и не создавая наследников. Они позволяют расширять классы и интерфейсы, даже если у нас нет доступа к их исходному коду.
Это обычные статические методы, но объявленные внутри статического класса.
Первый параметр метода должен принимать тот тип, который мы хотим расширить, и перед ним ставится ключевое слово
this. После этого метод становится доступен как "встроенный" у этого типа.
Допустим, у нас есть строка, и мы хотим добавить метод
ToSnakeCase, который заменяет пробелы на нижние подчеркивания. using System;
public static class StringExtensions
{
public static string ToSnakeCase(this string str)
{
return str.Replace(" ", "_").ToLower();
}
}
class Program
{
static void Main()
{
string text = "Hello World";
Console.WriteLine(text.ToSnakeCase()); // hello_world
}
}
Добавим метод `SumEvenNumbers()`, который суммирует только четные числа в
List<int>. using System;
using System.Collections.Generic;
using System.Linq;
public static class ListExtensions
{
public static int SumEvenNumbers(this List<int> numbers)
{
return numbers.Where(n => n % 2 == 0).Sum();
}
}
class Program
{
static void Main()
{
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6 };
Console.WriteLine(numbers.SumEvenNumbers()); // 12 (2 + 4 + 6)
}
}
Когда нужно добавить новый метод к существующему классу, но нельзя изменить его код (например,
string, List<T>, DateTime). Когда хочется сделать код более читаемым:
numbers.SumEvenNumbers() лучше, чем MyExtensions.SumEvenNumbers(numbers). Когда нужно улучшить API без наследования и изменения структуры классов.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍1
Это шаблон проектирования, который управляет взаимодействием между различными компонентами системы. Вместо того чтобы модули напрямую взаимодействовали друг с другом, они используют медиатор для коммуникации. Это снижает связанность системы и упрощает добавление новых модулей.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥3❤2
Это технология, обеспечивающая двустороннюю связь между клиентом и сервером через один TCP-соединение. В отличие от традиционного HTTP, который работает по принципу запрос-ответ, WebSockets позволяют передавать данные в обоих направлениях в режиме реального времени, что делает их идеальными для приложений, требующих мгновенного обмена данными.
Клиент и сервер могут отправлять данные друг другу независимо, без необходимости инициировать новый запрос.
После установления WebSocket-соединение остается открытым, что позволяет передавать данные с минимальной задержкой.
Меньшие накладные расходы по сравнению с HTTP, так как заголовки передаются только при установлении соединения, а не для каждого сообщения.
Поддержка большого количества одновременных соединений, что полезно для чатов, игр и других приложений с интенсивным обменом данными.
Клиент инициирует соединение с сервером через HTTP-запрос с заголовком
Upgrade, указывая, что он хочет перейти на WebSocket-протокол.Сервер отвечает согласием на переход на WebSocket-протокол, и соединение устанавливается.
После установления соединения данные могут передаваться в обоих направлениях до тех пор, пока одно из сторон не закроет соединение.
Сервер на Python с использованием библиотеки
websocketsimport asyncio
import websockets
async def handler(websocket, path):
async for message in websocket:
print(f"Received message: {message}")
await websocket.send(f"Echo: {message}")
start_server = websockets.serve(handler, "localhost", 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
Клиент на JavaScript
const socket = new WebSocket('ws://localhost:8765');
socket.onopen = function(event) {
console.log('WebSocket is open now.');
socket.send('Hello, Server!');
};
socket.onmessage = function(event) {
console.log(`Message from server: ${event.data}`);
};
socket.onclose = function(event) {
console.log('WebSocket is closed now.');
};
socket.onerror = function(error) {
console.log(`WebSocket error: ${error}`);
};Подходит для приложений, где важна минимальная задержка, таких как чаты, игровые приложения и финансовые торговые платформы.
Меньшее количество данных передается по сети по сравнению с традиционными HTTP-запросами.
Простота в использовании и поддержка большинством современных браузеров.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7😁2🔥1🤯1
Конкурентные коллекции — это специализированные коллекции, которые обеспечивают безопасное выполнение операций в многопоточной среде. В стандартной библиотеке .NET существуют несколько типов таких коллекций, каждая из которых предназначена для различных сценариев использования. Давайте рассмотрим основные из них.
Это словарь, который позволяет безопасно добавлять, удалять и изменять элементы из нескольких потоков одновременно. Он реализует интерфейс
IDictionary<TKey, TValue>.var concurrentDictionary = new ConcurrentDictionary<int, string>();
concurrentDictionary.TryAdd(1, "value1");
concurrentDictionary.TryAdd(2, "value2");
string value;
if (concurrentDictionary.TryGetValue(1, out value))
{
Console.WriteLine(value); // Output: value1
}
Это очередь, которая обеспечивает безопасное добавление элементов в конец и извлечение из начала в многопоточной среде. Она реализует интерфейс
IProducerConsumerCollection<T>.var concurrentQueue = new ConcurrentQueue<int>();
concurrentQueue.Enqueue(1);
concurrentQueue.Enqueue(2);
int result;
if (concurrentQueue.TryDequeue(out result))
{
Console.WriteLine(result); // Output: 1
}
Это стек, который обеспечивает безопасное добавление и извлечение элементов в многопоточной среде. Он также реализует интерфейс
IProducerConsumerCollection<T>.var concurrentStack = new ConcurrentStack<int>();
concurrentStack.Push(1);
concurrentStack.Push(2);
int result;
if (concurrentStack.TryPop(out result))
{
Console.WriteLine(result); // Output: 2
}
Это коллекция, которая позволяет безопасно добавлять и извлекать элементы в многопоточной среде. Она не гарантирует порядок элементов, поэтому используется в случаях, когда порядок не имеет значения.
var concurrentBag = new ConcurrentBag<int>();
concurrentBag.Add(1);
concurrentBag.Add(2);
int result;
if (concurrentBag.TryTake(out result))
{
Console.WriteLine(result); // Output: 1 или 2
}
Это коллекция, которая поддерживает ограниченную емкость и блокировку потоков при добавлении или извлечении элементов. Она особенно полезна для реализации паттернов продюсер-потребитель.
var blockingCollection = new BlockingCollection<int>(boundedCapacity: 5);
Task.Run(() =>
{
for (int i = 0; i < 10; i++)
{
blockingCollection.Add(i);
Console.WriteLine($"Added {i}");
}
blockingCollection.CompleteAdding();
});
foreach (var item in blockingCollection.GetConsumingEnumerable())
{
Console.WriteLine($"Consumed {item}");
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤1
Forwarded from easyoffer
💡 В EasyOffer 2.0 появится фильтрация вопросов по грейдам и типам интервью!
📊 Например, вот вероятности ТОП-30 вопросов, которые задают на HR-скрининге Python-разработчику уровня Middle/Senior. Данные основаны на 53 реальных интервью.
97% Какие у тебя зарплатные ожидания
73% Какие у тебя есть вопросы
44% Какие критерии при выборе будущей работы
41% Расскажи о себе
38% Почему ищешь работу
35% Расскажи про свой опыт
35% Расскажи про проект на предыдущей работе
32% Почему уволился с предыдущей работы
29% Где территориально сейчас живешь/находишься
23% Есть ли другие предложения по работе
17% Есть ли военный билет
17% Почему хочешь сменить работу
17% Как проводишь свободное время
17% Расскажи про задачи на предыдущей работе
17% Сколько коммерческого опыта работы с Python
17% С какими БД работал
14% Находишься ли в активном поиске работы
14% С каким стеком работаешь
14% Почему решил откликнуться на нашу вакансию
14% Какой текущий статус поиска работы
11% Почему решил стать программистом
11% С какими фреймворками работал
11% Какую зарплату получал на предыдущей работе
11% Работаешь ли в настоящий момент
11% На какой грейд себя оцениваешь
11% Как быстро можешь приступить к работе после получения офера
11% Расскажи про свои pet-проекты
8% Какие знаешь типы данных в Python
8% Что такое декоратор в Python
8% Что ищешь на новой работе
🚀 Скоро стартует краудфандинговая кампания, которая поможет ускорить разработку EasyOffer 2.0.
Первые спонсоры получат уникальные лимитированные награды!
📢 Если вам это интересно, подписывайтесь на канал 👉 этот телеграм канал
📊 Например, вот вероятности ТОП-30 вопросов, которые задают на HR-скрининге Python-разработчику уровня Middle/Senior. Данные основаны на 53 реальных интервью.
97% Какие у тебя зарплатные ожидания
73% Какие у тебя есть вопросы
44% Какие критерии при выборе будущей работы
41% Расскажи о себе
38% Почему ищешь работу
35% Расскажи про свой опыт
35% Расскажи про проект на предыдущей работе
32% Почему уволился с предыдущей работы
29% Где территориально сейчас живешь/находишься
23% Есть ли другие предложения по работе
17% Есть ли военный билет
17% Почему хочешь сменить работу
17% Как проводишь свободное время
17% Расскажи про задачи на предыдущей работе
17% Сколько коммерческого опыта работы с Python
17% С какими БД работал
14% Находишься ли в активном поиске работы
14% С каким стеком работаешь
14% Почему решил откликнуться на нашу вакансию
14% Какой текущий статус поиска работы
11% Почему решил стать программистом
11% С какими фреймворками работал
11% Какую зарплату получал на предыдущей работе
11% Работаешь ли в настоящий момент
11% На какой грейд себя оцениваешь
11% Как быстро можешь приступить к работе после получения офера
11% Расскажи про свои pet-проекты
8% Какие знаешь типы данных в Python
8% Что такое декоратор в Python
8% Что ищешь на новой работе
🚀 Скоро стартует краудфандинговая кампания, которая поможет ускорить разработку EasyOffer 2.0.
Первые спонсоры получат уникальные лимитированные награды!
📢 Если вам это интересно, подписывайтесь на канал 👉 этот телеграм канал
🤔1
- Для примитивных типов, таких как int, double, значения сравниваются напрямую.
- Для ссылочных типов сравниваются ссылки (адреса в памяти), если метод Equals не переопределён.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11