Anonymous Quiz
92%
Позволяют писать код, работающий с любыми типами данных.
5%
Позволяют сериализовать данные.
2%
Используются для работы с базами данных.
1%
Обеспечивают логирование приложений.
Легко масштабировать только те части системы, которые требуют этого, без необходимости масштабировать всё приложение. Например, если у вас есть микросервис, обрабатывающий заказы, и он испытывает высокую нагрузку, вы можете масштабировать только его, не трогая другие части системы.
Микросервисы можно развёртывать, обновлять и откатывать независимо друг от друга. Например вы можете обновить микросервис аутентификации без остановки микросервиса каталога продуктов.
Отказ одного микросервиса не приводит к отказу всего приложения. Например, если микросервис обработки платежей выходит из строя, пользователи всё равно могут просматривать продукты и добавлять их в корзину.
Каждый микросервис может быть написан на своем языке программирования и использовать свои технологии, что позволяет выбирать наиболее подходящие инструменты для каждой задачи. Например, Вы можете использовать Python для микросервиса машинного обучения и .NET для микросервиса управления пользователями.
Малые команды могут работать над разными микросервисами параллельно, что ускоряет процесс разработки. Например, одна команда может работать над микросервисом управления пользователями, в то время как другая команда работает над микросервисом заказа.
Управление множеством микросервисов требует сложной инфраструктуры для оркестрации, мониторинга и логирования. Например, вам нужно внедрить систему оркестрации, такую как Kubernetes, чтобы управлять развертыванием и масштабированием микросервисов.
Необходимо наладить надежные межсервисные коммуникации, что может быть сложно и привести к повышенным накладным расходам. Например, вам нужно решить, использовать ли синхронные (HTTP/REST) или асинхронные (сообщения, очереди) методы связи между микросервисами.
Тестирование микросервисной архитектуры сложнее из-за необходимости интеграции и взаимодействия между множеством независимых компонентов. Например вам нужно создать среду для интеграционного тестирования, которая включает все необходимые микросервисы.
Согласованность данных и управление транзакциями становятся более сложными задачами в распределённой системе. Например, вам нужно внедрить сложные механизмы для обеспечения согласованности данных, такие как саги или распределённые транзакции.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
Anonymous Quiz
71%
var dict = new Dictionary<int, string>();
16%
Dictionary<int, string> dict = new Dictionary();
3%
var dict = new Dictionary<int>();
11%
Dictionary dict = new Dictionary<int, string>();
🤯16🤔1👾1
Паттерн "Разделяй и властвуй" (Divide and Conquer) разделяет задачи на более мелкие подзадачи для упрощения кода и повышения эффективности.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🤯2
Anonymous Quiz
50%
var name = obj?.ToString();
10%
var name = obj?.Name();
32%
var name = obj?.Name;
7%
var name = obj?.GetName;
🤔9👍2👀1
Records:
Предназначены для создания неизменяемых типов данных с минимальным шаблонным кодом
public record Person(string FirstName, string LastName);
Init-only Properties:
Позволяют устанавливать значения свойств только при инициализации объекта.
public class Person
{
public string FirstName { get; init; }
public string LastName { get; init; }
}
With-expressions:
Используются для создания копий неизменяемых объектов с изменёнными значениями.
var person1 = new Person("John", "Doe");
var person2 = person1 with { LastName = "Smith" };Top-level Statements:
Позволяют писать код без явного класса или метода
Main.using System;
Console.WriteLine("Hello, World!");
Pattern Matching Enhancements:
Улучшения в сопоставлении с образцом, включая логические шаблоны (
and, or, not) и шаблоны типа is.if (person is Person { FirstName: "John", LastName: "Doe" })
{
Console.WriteLine("It's John Doe!");
} Global using directives:
Позволяют объявлять
using директивы, применимые ко всему проекту.// В globalusing.cs
global using System;
global using System.Collections.Generic;
File-scoped Namespace:
Упрощённый синтаксис для объявления пространства имён для всего файла.
namespace MyNamespace;
class MyClass { }
Record Structs:
Записи, которые могут быть значимыми типами.
public record struct Point(int X, int Y);
Improved `lambda` expressions:
Улучшения в синтаксисе и типизации лямбда-выражений.
Func<int, int> square = x => x * x;
Required Members:
Обязательные члены, которые должны быть установлены при создании объекта.
public class Person
{
public required string FirstName { get; init; }
public required string LastName { get; init; }
}
Raw String Literals:
Упрощённый синтаксис для создания многострочных строковых литералов без экранирования.
var json = """
{
"name": "John Doe",
"age": 30
}
""";
Generic Attributes:
Позволяют создавать атрибуты с обобщёнными параметрами.
[AttributeUsage(AttributeTargets.Class)]
public class MyGenericAttribute<T> : Attribute { }
[MyGenericAttribute<int>]
public class MyClass { }
List Pattern Matching:
Сопоставление с образцом для списков.
if (numbers is [1, 2, .., 10])
{
Console.WriteLine("The list starts with 1, 2 and ends with 10.");
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31❤2
Anonymous Quiz
78%
public async Task<int> GetData() { return await Task.FromResult(42); }
3%
public async int GetData() { return 42; }
13%
public Task<int> GetData() { return Task.FromResult(42); }
5%
public async Task GetData() { return 42; }
🤯7
Для оптимизации LINQ запросов в C# используйте компилируемые запросы, минимизируйте запросы в циклах, выбирайте только нужные поля, применяйте отложенное выполнение и метод
.AsNoTracking() для чтения данных.LINQ-запросы не выполняются до тех пор, пока не начнётся итерация по ним. Это позволяет объединить несколько операций в один запрос к базе данных.
var query = dbContext.Users.Where(u => u.IsActive); // Запрос ещё не выполнен
var activeUsers = query.ToList(); // Запрос выполнен здесь
Избегайте ненужных вызовов
ToList и ToArray, так как они приводят к немедленному выполнению запроса и загрузке всех данных в память.var users = dbContext.Users.Where(u => u.IsActive).ToList(); // Не вызывайте ToList() до тех пор, пока не нужно
Выбирайте только необходимые поля, чтобы уменьшить объем данных, передаваемых по сети и загружаемых в память.
var userNames = dbContext.Users
.Where(u => u.IsActive)
.Select(u => new { u.FirstName, u.LastName })
.ToList();
Фильтруйте данные на уровне базы данных, а не в памяти, чтобы уменьшить количество передаваемых данных.
var activeUsers = dbContext.Users.Where(u => u.IsActive).ToList(); // Фильтрация на уровне базы данных
Используйте пагинацию для работы с большими наборами данных, чтобы загружать и обрабатывать только нужные страницы.
var pageNumber = 2;
var pageSize = 10;
var paginatedUsers = dbContext.Users
.Where(u => u.IsActive)
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.ToList();
Сложные LINQ-запросы в циклах могут привести к многочисленным запросам к базе данных. Постарайтесь минимизировать их или объединить в один запрос.
// Плохо
foreach (var userId in userIds)
{
var user = dbContext.Users.FirstOrDefault(u => u.Id == userId);
}
// Хорошо
var users = dbContext.Users.Where(u => userIds.Contains(u.Id)).ToList();
Асинхронные методы, такие как
ToListAsync, FirstOrDefaultAsync и SingleOrDefaultAsync, помогают избежать блокировки потоков и улучшить производительность.var activeUsers = await dbContext.Users.Where(u => u.IsActive).ToListAsync();
Для часто выполняемых запросов используйте
EF.CompileQuery в Entity Framework, чтобы уменьшить накладные расходы на компиляцию запросов.private static readonly Func<MyDbContext, bool, IQueryable<User>> GetActiveUsersQuery =
EF.CompileQuery((MyDbContext context, bool isActive) =>
context.Users.Where(u => u.IsActive == isActive));
var activeUsers = GetActiveUsersQuery(dbContext, true).ToList();
Используйте инструменты профилирования и логирования для анализа генерируемых SQL-запросов, чтобы найти потенциальные узкие места и неэффективные запросы.
var sql = dbContext.Users.Where(u => u.IsActive).ToQueryString();
Console.WriteLine(sql);
Убедитесь, что индексы в базе данных настроены правильно для часто выполняемых запросов, чтобы улучшить производительность поиска.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍25
Anonymous Quiz
59%
var tuple = new Tuple<int, string>(1, "one");
9%
var tuple = Tuple.Create(1, "one");
12%
var tuple = new Tuple(1, "one");
20%
var tuple = (1, "one");
👍6👀5🤔3😁2
Обработка исключений в C# необходима для правильного управления ошибками, возникающими во время выполнения программы. Она позволяет перехватывать ошибки и выполнять соответствующие действия, чтобы программа не завершалась аварийно. Рассмотрим основные конструкции для обработки исключений:
try, catch, finally, и throw.Конструкция
try-catch используется для перехвата и обработки исключений. Код, который может вызвать исключение, помещается в блок try, а код для обработки исключения - в блок catch. try
{
// Код, который может вызвать исключение
int result = 10 / 0;
}
catch (DivideByZeroException ex)
{
// Обработка исключения
Console.WriteLine("Произошло деление на ноль: " + ex.Message);
}
catch (Exception ex)
{
// Обработка других исключений
Console.WriteLine("Произошла ошибка: " + ex.Message);
}
Блок
finally выполняется в любом случае после завершения блоков try и catch, независимо от того, возникло исключение или нет. Он часто используется для освобождения ресурсов, таких как файловые дескрипторы или сетевые подключения. try
{
// Код, который может вызвать исключение
using (StreamReader sr = new StreamReader("file.txt"))
{
// Чтение файла
}
}
catch (FileNotFoundException ex)
{
// Обработка исключения
Console.WriteLine("Файл не найден: " + ex.Message);
}
finally
{
// Очистка ресурсов
Console.WriteLine("Закрытие файла.");
}
Ключевое слово
throw используется для генерации исключений. Оно может быть использовано как для передачи возникшего исключения дальше по цепочке вызовов, так и для создания нового исключения. void ProcessNumber(int number)
{
if (number < 0)
{
throw new ArgumentOutOfRangeException("number", "Число должно быть неотрицательным");
}
// Продолжение обработки
}
Вложенные исключения позволяют захватывать одно исключение и генерировать новое, сохраняя информацию о первоначальном исключении.
try
{
// Код, который может вызвать исключение
MethodThatThrows();
}
catch (Exception ex)
{
throw new InvalidOperationException("Ошибка в процессе выполнения", ex);
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Anonymous Quiz
13%
var result = from x in list where x > 10;
5%
var result = list.Find(x => x > 10);
8%
var result = list.Filter(x => x > 10);
75%
var result = list.Where(x => x > 10);
🤯7
Использование специализированных исключений, таких как
ArgumentException, InvalidOperationException, или пользовательских исключений (например, MyCustomException), лучше, чем использование общего исключения Exception. Это позволяет более точно и детально управлять ошибками.Специализированные исключения помогают точнее определить, что именно пошло не так. Например,
ArgumentNullException ясно указывает, что переданный аргумент был null, в то время как Exception может означать любую ошибку. void ProcessData(string data)
{
if (data == null)
{
throw new ArgumentNullException(nameof(data), "Data cannot be null");
}
// Обработка данных
}
Использование конкретных исключений делает код более читаемым и поддерживаемым. Разработчики, читающие код, сразу понимают, какие именно ошибки могут возникнуть и как с ними справляться.
try
{
// Код, который может вызвать исключение
}
catch (ArgumentNullException ex)
{
// Обработка ситуации, когда аргумент был null
}
catch (InvalidOperationException ex)
{
// Обработка некорректного состояния операции
}
Специализированные исключения предоставляют больше информации для отладки. Это позволяет быстрее найти и исправить ошибки, так как разработчики получают более точные сообщения об ошибках.
try
{
// Код, который может вызвать исключение
}
catch (Exception ex)
{
// Общее исключение, трудно определить причину
Console.WriteLine("Произошла ошибка: " + ex.Message);
}
С помощью специализированных исключений можно различать разные типы ошибок и применять к ним разные стратегии обработки. Это делает обработку ошибок более гибкой и точной.
try
{
// Код, который может вызвать исключение
}
catch (ArgumentNullException ex)
{
Console.WriteLine("Обязательный аргумент не был передан: " + ex.Message);
// Специфическая обработка для отсутствующего аргумента
}
catch (ArgumentException ex)
{
Console.WriteLine("Аргумент некорректен: " + ex.Message);
// Специфическая обработка для некорректного аргумента
}
В сложных приложениях можно создавать пользовательские исключения, которые более точно описывают уникальные ошибки, специфичные для вашего приложения.
public class MyCustomException : Exception
{
public MyCustomException(string message) : base(message) { }
}
void DoSomething()
{
throw new MyCustomException("Произошла специфическая ошибка.");
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🤔1🤯1👾1
Anonymous Quiz
68%
public readonly int x = 10;
2%
public int x = 10;
12%
public static readonly int x = 10;
19%
readonly int x;
🤯21😁4
Создание своих исключений в 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
Anonymous Quiz
3%
Типы данных, которые нельзя изменять.
95%
Типы, которые могут принимать значение null.
1%
Типы, используемые для сериализации.
1%
Типы, используемые для работы с потоками.
😁14🤯5
Валидация входных данных помогает предотвратить атаки, такие как 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 атак.
<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
Anonymous Quiz
5%
ToString.
3%
Parse.
3%
Convert.
89%
Serialize.
🤯12🤔3👍1👀1
Работа с асинхронными операциями в C# важна для создания производительных и отзывчивых приложений, особенно когда дело касается операций ввода-вывода, сетевых запросов или длительных вычислений. В C# для этого используется ключевые слова
async и await, а также Task и Task<T>. `async`: Указывает, что метод является асинхронным и может содержать операторы
await.`await`: Используется для ожидания завершения асинхронной операции без блокировки основного потока.
`Task`: Представляет асинхронную операцию без возвращаемого значения.
`Task<T>`: Представляет асинхронную операцию, возвращающую значение типа
T.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-запросов можно использовать
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
👍10❤1
Тестирование программного обеспечения включает планирование тестов, их выполнение для проверки функциональности и других аспектов, а отладка занимается устранением найденных в ходе тестирования ошибок через анализ кода и логов.
Visual Studio предоставляет мощные инструменты отладки. Основные возможности включают установку точек останова (breakpoints), пошаговое выполнение кода (step over, step into, step out), просмотр значений переменных и выражений.
Для вывода отладочной информации можно использовать классы
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.");
}
}
Использование журналирования позволяет записывать события и ошибки во время выполнения приложения. В .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