C# | Вопросы собесов
5.1K subscribers
34 photos
1 file
980 links
Download Telegram
🤯21😁4
🤔 Зачем может понадобиться делать свой exception?

Создание своих исключений в C# может понадобиться в ряде случаев, когда стандартные исключения не подходят для описания специфических ошибок, возникающих в вашем приложении.

🟠Специфичность и Контекст
Свои исключения позволяют дать более точное описание ошибки, связанной с конкретной бизнес-логикой или контекстом приложения. Это делает код более понятным и легким для сопровождения.
public class InsufficientFundsException : Exception
{
public InsufficientFundsException(string message) : base(message) { }
}

public class BankAccount
{
public void Withdraw(decimal amount)
{
if (amount > Balance)
{
throw new InsufficientFundsException("Недостаточно средств на счете.");
}
// Логика снятия средств
}
}


🟠Улучшение Отладки и Логирования
Свои исключения могут включать дополнительную информацию, которая поможет лучше понять контекст ошибки при отладке или логировании.
public class DataNotFoundException : Exception
{
public string DataId { get; }

public DataNotFoundException(string dataId, string message) : base(message)
{
DataId = dataId;
}
}

void GetData(string id)
{
// Если данные не найдены
throw new DataNotFoundException(id, "Данные не найдены для ID: " + id);
}


🟠Группировка Исключений
Создание своих исключений позволяет логически группировать ошибки, что облегчает их обработку в коде. Например, можно создать базовое исключение для всех ошибок, связанных с доступом к базе данных, и наследовать от него конкретные типы ошибок.
public class DatabaseException : Exception
{
public DatabaseException(string message) : base(message) { }
}

public class RecordNotFoundException : DatabaseException
{
public RecordNotFoundException(string message) : base(message) { }
}

public class ConnectionFailedException : DatabaseException
{
public ConnectionFailedException(string message) : base(message) { }
}


🟠Соответствие Архитектуре
В сложных системах с многоуровневой архитектурой свои исключения помогают управлять ошибками на каждом уровне, передавая их на более высокий уровень для централизованной обработки.
public class BusinessException : Exception
{
public BusinessException(string message) : base(message) { }
}

public class PaymentProcessingException : BusinessException
{
public PaymentProcessingException(string message) : base(message) { }
}

void ProcessPayment()
{
try
{
// Логика обработки платежа
}
catch (Exception ex)
{
throw new PaymentProcessingException("Ошибка при обработке платежа: " + ex.Message);
}
}


🟠Обеспечение Лучшего Взаимодействия с Пользователем
Пользовательские исключения могут содержать информацию, которая будет полезна для отображения пользователю, улучшая пользовательский опыт.
public class UserNotAuthorizedException : Exception
{
public UserNotAuthorizedException(string message) : base(message) { }
}

void AccessRestrictedArea()
{
if (!userIsAuthorized)
{
throw new UserNotAuthorizedException("Пользователь не имеет права доступа к этому разделу.");
}
// Логика доступа
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9😁1
🤔 Какие принципы и практики используешь для обеспечения безопасности приложений?

🟠Валидация и Санитизация Входных Данных
Валидация входных данных помогает предотвратить атаки, такие как SQL-инъекции, XSS (межсайтовый скриптинг) и другие. SQL-инъекции: Используйте параметризованные запросы или ORM (например, Entity Framework).
using (SqlCommand cmd = new SqlCommand("SELECT * FROM Users WHERE Username = @username", conn))
{
cmd.Parameters.AddWithValue("@username", username);
// Выполнение команды
}


XSS: Используйте библиотеку для экранирования HTML, например, AntiXSS.
string safeContent = Microsoft.Security.Application.Encoder.HtmlEncode(userInput);


🟠Использование Аутентификации и Авторизации
Обеспечьте надежную аутентификацию и разграничение доступа к ресурсам.
Аутентификация: Используйте современные методы аутентификации, такие как OAuth, OpenID Connect.
Авторизация: Применяйте ролевую или заявочную (claims-based) авторизацию.
[Authorize(Roles = "Admin")]
public IActionResult AdminOnly()
{
return View();
}


🟠Защита от CSRF (Межсайтовая подделка запросов)
Используйте анти-CSRF токены для защиты от CSRF атак.
<form asp-action="Create">
<input type="hidden" name="__RequestVerificationToken" value="@Antiforgery.GetTokens(HttpContext).RequestToken" />
<!-- Другие поля формы -->
</form>


🟠Шифрование и Защита Данных
Шифруйте чувствительные данные как при передаче, так и при хранении.
При передаче: Используйте HTTPS для шифрования данных, передаваемых через сеть.
При хранении: Используйте библиотеки для шифрования, такие как System.Security.Cryptography.
using (Aes aes = Aes.Create())
{
aes.Key = key;
aes.IV = iv;
// Шифрование данных
}


🟠Логирование и Мониторинг
Внедрите логирование и мониторинг для обнаружения и анализа подозрительной активности.
Логирование: Логируйте важные действия, такие как входы в систему, изменения данных.
Мониторинг: Используйте инструменты мониторинга, такие как Application Insights, для отслеживания состояния приложения.
_logger.LogInformation("User {UserId} logged in.", userId);


🟠Управление Ошибками и Исключениями
Не показывайте подробные сообщения об ошибках пользователям, чтобы не раскрывать внутреннюю структуру приложения.
Обработка исключений: Ловите и корректно обрабатывайте исключения, предоставляя пользователю дружелюбные сообщения.
try
{
// Код, который может вызвать исключение
}
catch (Exception ex)
{
_logger.LogError(ex, "Произошла ошибка.");
return View("Error");
}


🟠Обновления и Патчи
Регулярно обновляйте используемые библиотеки и фреймворки, чтобы закрывать уязвимости.

🟠Минимизация Поверхности Атаки
Удалите или отключите ненужные функции и сервисы, чтобы минимизировать возможные точки входа для атак.

🟠Защита Конфигурации
Защитите конфигурационные файлы, содержащие чувствительную информацию.
Секреты и ключи: Используйте секреты и безопасное хранилище для конфиденциальной информации.
var connectionString = Configuration["ConnectionStrings:DefaultConnection"];


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
🤔 Какой метод используется для сериализации объекта в C#?
Anonymous Quiz
5%
ToString.
3%
Parse.
3%
Convert.
89%
Serialize.
🤯12🤔3👍1👀1
🤔 Как работаешь с асинхронными операциями?

Работа с асинхронными операциями в C# важна для создания производительных и отзывчивых приложений, особенно когда дело касается операций ввода-вывода, сетевых запросов или длительных вычислений. В C# для этого используется ключевые слова async и await, а также Task и Task<T>.

🚩Основные Концепции

🟠Ключевые слова `async` и `await`
`async`: Указывает, что метод является асинхронным и может содержать операторы await.
`await`: Используется для ожидания завершения асинхронной операции без блокировки основного потока.

🟠Task и Task<T>
`Task`: Представляет асинхронную операцию без возвращаемого значения.
`Task<T>`: Представляет асинхронную операцию, возвращающую значение типа T.

🚩Пример Асинхронного Метода

🟠Рассмотрим пример простого асинхронного метода, который выполняет задержку на 2 секунды.
public async Task DelayExampleAsync()
{
Console.WriteLine("Начало задержки");
await Task.Delay(2000); // Асинхронная задержка на 2 секунды
Console.WriteLine("Завершение задержки");
}


🟠Асинхронный Ввод-Вывод
Асинхронные операции ввода-вывода часто используются для работы с файлами, сетевыми запросами и базами данных. Пример асинхронного чтения файла:
public async Task<string> ReadFileAsync(string filePath)
{
using (StreamReader reader = new StreamReader(filePath))
{
return await reader.ReadToEndAsync();
}
}


🟠Асинхронные HTTP-запросы
Для выполнения асинхронных HTTP-запросов можно использовать HttpClient.
public async Task<string> FetchDataFromApiAsync(string url)
{
using (HttpClient client = new HttpClient())
{
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}


🟠Обработка Исключений в Асинхронных Методах
Обработка исключений в асинхронных методах аналогична синхронным методам, с использованием блоков try-catch.
public async Task<string> SafeFetchDataFromApiAsync(string url)
{
try
{
using (HttpClient client = new HttpClient())
{
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Ошибка запроса: {ex.Message}");
return string.Empty;
}
}


🟠Совместное Выполнение Асинхронных Операций
Для выполнения нескольких асинхронных операций параллельно можно использовать Task.WhenAll или Task.WhenAny.
public async Task PerformMultipleTasksAsync()
{
Task<int> task1 = Task.Run(() => ComputeAsync(10));
Task<int> task2 = Task.Run(() => ComputeAsync(20));

int[] results = await Task.WhenAll(task1, task2);
Console.WriteLine($"Результаты: {results[0]}, {results[1]}");
}

public async Task<int> ComputeAsync(int value)
{
await Task.Delay(1000);
return value * value;
}


🟠Пример Полного Асинхронного Приложения
Рассмотрим пример асинхронного метода, который загружает данные из нескольких URL и выводит их размер.
public async Task FetchDataFromMultipleUrlsAsync(string[] urls)
{
List<Task<string>> fetchTasks = new List<Task<string>>();

foreach (string url in urls)
{
fetchTasks.Add(FetchDataFromApiAsync(url));
}

string[] results = await Task.WhenAll(fetchTasks);

foreach (string result in results)
{
Console.WriteLine($"Длина данных: {result.Length}");
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍101
🤔 Как проводить тестирование и отладку?

Тестирование программного обеспечения включает планирование тестов, их выполнение для проверки функциональности и других аспектов, а отладка занимается устранением найденных в ходе тестирования ошибок через анализ кода и логов.

🟠Использование отладчика (Debugger)
Visual Studio предоставляет мощные инструменты отладки. Основные возможности включают установку точек останова (breakpoints), пошаговое выполнение кода (step over, step into, step out), просмотр значений переменных и выражений.

1⃣Установка точки останова: Нажмите слева от строки кода, где нужно остановиться, или используйте клавишу F9.
2⃣Запуск отладки: Нажмите F5 или выберите "Debug -> Start Debugging".
3⃣Пошаговое выполнение: Используйте F10 (step over), F11 (step into) и Shift+F11 (step out).

🟠Использование `Debug` и `Trace`
Для вывода отладочной информации можно использовать классы Debug и Trace из пространства имен System.Diagnostics.
using System.Diagnostics;

public class Program
{
public static void Main()
{
Debug.WriteLine("This is a debug message.");
Trace.WriteLine("This is a trace message.");
}
}


🟠Журналирование (Logging)
Использование журналирования позволяет записывать события и ошибки во время выполнения приложения. В .NET Core и ASP.NET Core используется встроенная система логирования.
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;

public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}

public IActionResult Index()
{
_logger.LogInformation("Executing Index method");
return View();
}
}


🟠Анализ дампов памяти
В случае критических ошибок можно анализировать дампы памяти для диагностики проблем. Используйте WinDbg или Visual Studio для анализа дампов.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11
🤔 Что такое static?

Static - это ключевое слово, которое используется для объявления статических членов в классе. Статические члены принадлежат самому классу, а не его экземплярам.

🚩Основные моменты использования

🟠Поля
Статические поля объявляются с использованием ключевого слова static и принадлежат классу в целом. Все экземпляры класса разделяют одно и то же статическое поле.
public class Example
{
public static int Counter;
}

// Доступ к статическому полю
Example.Counter = 10;
Console.WriteLine(Example.Counter); // Выведет 10


🟠Методы
Статические методы могут быть вызваны без создания экземпляра класса. Статические методы могут обращаться только к другим статическим членам класса.
public class Calculator
{
public static int Add(int a, int b)
{
return a + b;
}
}

// Вызов статического метода
int sum = Calculator.Add(5, 3);
Console.WriteLine(sum); // Выведет 8


🟠Свойства
Статические свойства похожи на статические поля, но с доступом через методы get и set.
public class Configuration
{
private static string _setting;

public static string Setting
{
get { return _setting; }
set { _setting = value; }
}
}

// Доступ к статическому свойству
Configuration.Setting = "My Setting";
Console.WriteLine(Configuration.Setting); // Выведет "My Setting"


🟠Конструкторы
Статические конструкторы используются для инициализации статических членов класса. Они вызываются один раз при первом обращении к статическим членам.
public class Database
{
public static string ConnectionString;

static Database()
{
ConnectionString = "Initial Catalog=myDatabase;Data Source=myServer;";
}
}

// При первом доступе вызывается статический конструктор
Console.WriteLine(Database.ConnectionString); // Выведет строку подключения


🚩Зачем нужен?

🟠Общие данные и функции:
Статические члены полезны для хранения данных или функций, которые должны быть общими для всех экземпляров класса.
🟠Упрощение доступа:
Позволяет вызывать методы и свойства без необходимости создавать экземпляр класса.
🟠Инициализация ресурсов:
Статические конструкторы полезны для инициализации ресурсов или настройки параметров, необходимых для работы класса.

🚩Ограничения

🟠Статические методы не могут обращаться к нестатическим членам напрямую, так как у них нет доступа к экземпляру класса.
🟠Статические конструкторы не могут иметь параметры и вызываются автоматически при первом обращении к классу.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍121
🤔 В чём разница абстрактного класса и интерфейса?

Абстрактный класс может содержать как реализацию методов, так и абстрактные методы, а интерфейс — только определения методов без реализации. Абстрактные классы могут иметь поля и конструкторы, а интерфейсы — нет. Класс может наследовать только один абстрактный класс, но реализовать несколько интерфейсов. Интерфейсы предоставляют более гибкий способ организации контракта для классов.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10😁2👀1
🤔 Как работает static конструктор?

Статический конструктор в предназначен для инициализации статических членов класса или для выполнения действий, которые должны быть выполнены один раз для всего класса, а не для каждого его экземпляра.

🚩Основные характеристики

🟠Автоматический вызов:
Статический конструктор вызывается автоматически перед первым использованием любого статического члена класса или перед созданием первого экземпляра класса, в зависимости от того, что произойдет раньше.
🟠Единовременное выполнение:
Статический конструктор выполняется только один раз на весь период существования приложения.
🟠Без параметров:
Статический конструктор не может принимать параметры.
🟠Невозможность явного вызова:
Невозможно вызвать статический конструктор вручную. Он вызывается автоматически.

Рассмотрим класс, который использует статический конструктор для инициализации статического поля:
public class ConfigurationManager
{
public static string Configuration;

// Статический конструктор
static ConfigurationManager()
{
Configuration = "Default Configuration";
Console.WriteLine("Статический конструктор выполнен.");
}
}

class Program
{
static void Main()
{
// Обращение к статическому полю вызывает статический конструктор
Console.WriteLine(ConfigurationManager.Configuration);

// Создание экземпляра класса не вызовет статический конструктор снова
ConfigurationManager configManager = new ConfigurationManager();
Console.WriteLine(ConfigurationManager.Configuration);
}
}


1⃣Первое обращение к статическому члену:
Когда программа впервые обращается к ConfigurationManager.Configuration, вызывается статический конструктор класса ConfigurationManager.
2⃣Инициализация:
Внутри статического конструктора происходит инициализация статического поля Configuration.
3⃣Вывод:
В консоли будет выведено сообщение "Статический конструктор выполнен." и значение "Default Configuration".

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍61
🤔 Что такое Inversion of control и dependency injection?

Inversion of control (IoC) — это принцип, при котором управление созданием объектов передается внешним компонентам. Dependency injection (DI) — это один из способов реализации IoC, когда зависимости передаются объекту через конструктор, методы или свойства. Это позволяет улучшить тестируемость и модульность кода. DI делает систему более гибкой, позволяя изменять реализации зависимостей без изменения кода.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай
📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🔥4
🤔 Что такое статический полиморфизм?

Статический полиморфизм, также известный как полиморфизм на этапе компиляции, — это форма полиморфизма, при которой вызов метода или доступ к члену определяется во время компиляции, а не во время выполнения. Статический полиморфизм достигается с помощью таких механизмов, как перегрузка методов (method overloading) и обобщенные типы (generics).

🚩Перегрузка методов (Method Overloading)

Перегрузка методов позволяет иметь несколько методов с одинаковым именем, но разными параметрами (различные типы, количество или порядок параметров). Компилятор решает, какой метод вызвать, основываясь на переданных аргументах.
public class MathOperations
{
public int Add(int a, int b)
{
return a + b;
}

public double Add(double a, double b)
{
return a + b;
}

public int Add(int a, int b, int c)
{
return a + b + c;
}
}

class Program
{
static void Main()
{
MathOperations math = new MathOperations();

int result1 = math.Add(2, 3); // Вызовется метод Add(int, int)
double result2 = math.Add(2.5, 3.5); // Вызовется метод Add(double, double)
int result3 = math.Add(1, 2, 3); // Вызовется метод Add(int, int, int)

Console.WriteLine(result1); // Вывод: 5
Console.WriteLine(result2); // Вывод: 6.0
Console.WriteLine(result3); // Вывод: 6
}
}


🚩Обобщенные типы (Generics)

Обобщенные типы позволяют создавать классы, методы и структуры, работающие с любыми типами данных, обеспечивая безопасность типов на этапе компиляции и избегая затрат на приведение типов.
public class GenericCalculator<T>
{
public T Add(T a, T b)
{
dynamic da = a;
dynamic db = b;
return da + db;
}
}

class Program
{
static void Main()
{
GenericCalculator<int> intCalculator = new GenericCalculator<int>();
int intResult = intCalculator.Add(3, 4); // Вызов метода для типа int
Console.WriteLine(intResult); // Вывод: 7

GenericCalculator<double> doubleCalculator = new GenericCalculator<double>();
double doubleResult = doubleCalculator.Add(2.5, 3.7); // Вызов метода для типа double
Console.WriteLine(doubleResult); // Вывод: 6.2
}
}


🚩Отличия от динамического полиморфизма

🟠Статический полиморфизм определяется на этапе компиляции, в то время как динамический полиморфизм (также известный как позднее связывание или полиморфизм на этапе выполнения) определяется во время выполнения с помощью виртуальных методов и наследования.
В этом примере компилятор не знает заранее, какой метод Speak будет вызван, так как это определяется во время выполнения.
public class Animal
{
public virtual void Speak()
{
Console.WriteLine("Animal speaks");
}
}

public class Dog : Animal
{
public override void Speak()
{
Console.WriteLine("Dog barks");
}
}

class Program
{
static void Main()
{
Animal myAnimal = new Dog();
myAnimal.Speak(); // Вывод: Dog barks
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥1
🤔 Что такое принципы SOLID?

SOLID — это набор пяти принципов объектно-ориентированного программирования, которые помогают писать гибкий и поддерживаемый код. Принципы включают: Single Responsibility (одна ответственность), Open/Closed (открытость для расширения, закрытость для изменений), Liskov Substitution (подстановка Барбары Лисков), Interface Segregation (разделение интерфейсов) и Dependency Inversion (инверсия зависимостей). Эти принципы помогают избежать излишней сложности и улучшить структуру программного кода. Применение SOLID делает код более устойчивым к изменениям и легче в сопровождении.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14
🤔 Что такое полиморфизм подтипов?

Полиморфизм подтипов — это способность объектов разных классов, связанных отношениями наследования, обрабатываться единообразно. Это позволяет использовать объекты подклассов через ссылки на базовые классы, что делает код гибким и расширяемым.

🚩Основные понятия

🟠Наследование:
Классы могут наследовать другие классы, унаследуя их методы и свойства.
🟠Интерфейсы:
Классы могут реализовывать интерфейсы, обеспечивая конкретную реализацию методов интерфейса.
🟠Виртуальные методы:
Методы, объявленные как virtual в базовом классе, могут быть переопределены в производных классах с использованием ключевого слова override.
🟠Позднее связывание:
Метод, который будет вызван, определяется во время выполнения, а не во время компиляции.

Базовый класс и производные классы
public class Animal
{
// Виртуальный метод, который может быть переопределен в производных классах
public virtual void Speak()
{
Console.WriteLine("Animal speaks");
}
}

public class Dog : Animal
{
// Переопределение метода Speak для класса Dog
public override void Speak()
{
Console.WriteLine("Dog barks");
}
}

public class Cat : Animal
{
// Переопределение метода Speak для класса Cat
public override void Speak()
{
Console.WriteLine("Cat meows");
}
}


Использование полиморфизма подтипов
class Program
{
static void Main()
{
// Создание массива объектов типа Animal
Animal[] animals = new Animal[]
{
new Dog(),
new Cat(),
new Animal()
};

// Вызов метода Speak для каждого объекта в массиве
foreach (Animal animal in animals)
{
animal.Speak();
}
}
}


🟠Полиморфизм с интерфейсами
Полиморфизм также может быть достигнут через интерфейсы. В этом примере классы Dog и Cat реализуют интерфейс IAnimal, и метод Speak вызывается через интерфейс, что также демонстрирует полиморфизм подтипов.
public interface IAnimal
{
void Speak();
}

public class Dog : IAnimal
{
public void Speak()
{
Console.WriteLine("Dog barks");
}
}

public class Cat : IAnimal
{
public void Speak()
{
Console.WriteLine("Cat meows");
}
}

class Program
{
static void Main()
{
IAnimal[] animals = new IAnimal[]
{
new Dog(),
new Cat()
};

foreach (IAnimal animal in animals)
{
animal.Speak();
}
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4👾3
🤔 Что такое делегат?

Делегат в C# — это тип, который представляет ссылки на методы с определённой сигнатурой. Делегаты используются для передачи методов в качестве параметров и для обратных вызовов (callbacks). Они являются основой для событий и лямбда-выражений в C#. Делегаты позволяют вызывать методы динамически, что делает код более гибким.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥41👀1
🤔 Расскажи про принцип подстановки Барбары Лисков?

Принцип подстановки Барбары Лисков (Liskov Substitution Principle, LSP) является одним из пяти принципов объектно-ориентированного программирования, известных под акронимом SOLID.

🚩Основная идея LSP

Основная идея заключается в том, что если класс B является подтипом класса A, то объекты класса A могут быть заменены объектами класса B без изменения правильности работы программы. Это означает, что наследование должно использоваться так, чтобы производный класс сохранял поведение базового класса.

🚩Правила для соблюдения LSP

🟠Сохранение контрактов:
Производный класс должен соблюдать контракт, определённый базовым классом. Это включает в себя сигнатуры методов и ожидания (предусловия и постусловия).

🟠Инварианты класса:
Инварианты, или неизменяемые условия, которые выполняются для объектов базового класса, должны оставаться в силе и для объектов производного класса.

🟠Постусловия не должны быть ослаблены:
Производный класс не должен ослаблять постусловия методов базового класса. Постусловия - это условия, которые гарантированы после выполнения метода.

🟠Предусловия не должны быть усилены:
Производный класс не должен усиливать предусловия методов базового класса. Предусловия - это условия, которые должны быть выполнены перед вызовом метода. В этом примере Penguin нарушает LSP, так как он не может летать. Если заменить экземпляр FlyingBird на Penguin, программа перестанет работать правильно.
public abstract class Bird
{
public abstract void Fly();
}

public class FlyingBird : Bird
{
public override void Fly()
{
Console.WriteLine("I can fly!");
}
}

public class Penguin : Bird
{
public override void Fly()
{
throw new NotSupportedException("Penguins cannot fly.");
}
}


Теперь классы FlyingBird и Penguin оба наследуют класс Bird и реализуют метод Move, но каждый делает это по-своему, не нарушая LSP.
public abstract class Bird
{
public abstract void Move();
}

public class FlyingBird : Bird
{
public override void Move()
{
Fly();
}

private void Fly()
{
Console.WriteLine("I can fly!");
}
}

public class Penguin : Bird
{
public override void Move()
{
Console.WriteLine("I waddle.");
}
}


🚩Плюсы

Повышенная гибкость и расширяемость:
Код, который соблюдает LSP, легче модифицировать и расширять без риска нарушения существующей функциональности.
Упрощённое тестирование:
Код, соответствующий LSP, легче тестировать, так как можно заменять объекты их подтипами в тестах без изменения поведения.
Повышенная поддерживаемость:
Такой код легче поддерживать и рефакторить, так как контракт между базовым и производным классами чётко определён и соблюдается.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍132
🤔 Что такое middleware в ASP.NET core?

Middleware — это компоненты, которые обрабатывают HTTP-запросы и ответы в ASP.NET Core. Каждый компонент middleware может либо обработать запрос, либо передать его следующему компоненту в конвейере. Они используются для выполнения задач, таких как аутентификация, логирование или обработка ошибок. Последовательность middleware определяет поведение приложения и порядок обработки запросов.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🔥8
🤔 Какие бывают типы?

Существует несколько типов данных, которые можно разделить на основные категории: простые типы, ссылочные типы, и пользовательские типы.

🚩Основные типы данных:

🟠Простые типы (Value Types)
Простые типы хранят значения непосредственно и включают примитивные типы, перечисления и структуры.

🟠Примитивные типы
Целочисленные типы:
byte (8-битный, от 0 до 255)
sbyte (8-битный, от -128 до 127)
short (16-битный, от -32,768 до 32,767)
ushort (16-битный, от 0 до 65,535)
int (32-битный, от -2,147,483,648 до 2,147,483,647)
uint (32-битный, от 0 до 4,294,967,295)
long (64-битный, от -9,223,372,036,854,775,808 до 9,223,372,036,854,775,807)
ulong (64-битный, от 0 до 18,446,744,073,709,551,615)

🟠Типы с плавающей запятой:
float (32-битный, ±1.5e−45 до ±3.4e38, 7 знаков точности)
double (64-битный, ±5.0e−324 до ±1.7e308, 15-16 знаков точности)

🟠Десятичные типы:
decimal (128-битный, ±1.0 × 10−28 до ±7.9 × 10^28, 28-29 знаков точности)

🟠Прочие простые типы:
char (16-битный символ Unicode)
bool (логический тип, принимает значения true или false)

🟠Структуры и перечисления
Структуры (struct): Пользовательские типы данных, которые являются значимыми типами и могут содержать поля, методы, свойства и т.д.
Перечисления (enum): Тип, представляющий набор именованных констант.

🟠Ссылочные типы (Reference Types)
Ссылочные типы хранят ссылку на область памяти, где находятся данные. К ним относятся классы, интерфейсы, делегаты и массивы.

🚩Классы и интерфейсы

🟠Классы (class):
Основной строительный блок объектно-ориентированного программирования, могут содержать поля, методы, свойства, события и т.д.
🟠Интерфейсы (interface):
Контракты, определяющие набор методов и свойств, которые должны быть реализованы классами.

🚩Делегаты и события

🟠Делегаты (delegate):
Типы, представляющие ссылку на методы. Используются для реализации обратных вызовов и событий.
🟠События (event):
Механизм, через который объекты могут сообщать о произошедших действиях.

🚩Массивы и строки

🟠Массивы (Array):
Коллекции элементов одного типа, доступ к которым осуществляется по индексу.
🟠Строки (string):
Неизменяемые последовательности символов.

🚩Пользовательские типы

Пользовательские типы могут быть созданы на основе простых и ссылочных типов.

🚩Кортежи и анонимные типы

🟠Кортежи (Tuple):
Группировка значений различных типов.
🟠Анонимные типы:
Типы, созданные для хранения наборов значений, определённых на лету.
🟠Nullable-типы
Позволяют значимым типам принимать значение null.
int? nullableInt = null; // Nullable int


Пример использования простых типов:
int age = 30;
double salary = 50000.50;
bool isEmployed = true;
char grade = 'A';


Пример использования классов и интерфейсов:
public interface IAnimal
{
void Speak();
}

public class Dog : IAnimal
{
public void Speak()
{
Console.WriteLine("Bark");
}
}


Пример использования структуры:
public struct Point
{
public int X;
public int Y;

public Point(int x, int y)
{
X = x;
Y = y;
}
}


Пример использования перечисления:
public enum DaysOfWeek
{
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍142