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
Anonymous Quiz
14%
Управляет потоками.
5%
Создает новую задачу.
80%
Отслеживает завершение асинхронной операции.
1%
Сериализует данные.
❤7
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
👍12❤1
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10😁2👀1
Статический конструктор в предназначен для инициализации статических членов класса или для выполнения действий, которые должны быть выполнены один раз для всего класса, а не для каждого его экземпляра.
Статический конструктор вызывается автоматически перед первым использованием любого статического члена класса или перед созданием первого экземпляра класса, в зависимости от того, что произойдет раньше.
Статический конструктор выполняется только один раз на весь период существования приложения.
Статический конструктор не может принимать параметры.
Невозможно вызвать статический конструктор вручную. Он вызывается автоматически.
Рассмотрим класс, который использует статический конструктор для инициализации статического поля:
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);
}
}
Когда программа впервые обращается к
ConfigurationManager.Configuration, вызывается статический конструктор класса ConfigurationManager.Внутри статического конструктора происходит инициализация статического поля
Configuration.В консоли будет выведено сообщение "Статический конструктор выполнен." и значение "Default Configuration".
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🔥4
Статический полиморфизм, также известный как полиморфизм на этапе компиляции, — это форма полиморфизма, при которой вызов метода или доступ к члену определяется во время компиляции, а не во время выполнения. Статический полиморфизм достигается с помощью таких механизмов, как перегрузка методов (method overloading) и обобщенные типы (generics).
Перегрузка методов позволяет иметь несколько методов с одинаковым именем, но разными параметрами (различные типы, количество или порядок параметров). Компилятор решает, какой метод вызвать, основываясь на переданных аргументах.
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
}
}
Обобщенные типы позволяют создавать классы, методы и структуры, работающие с любыми типами данных, обеспечивая безопасность типов на этапе компиляции и избегая затрат на приведение типов.
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
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
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
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥4❤1👀1
Принцип подстановки Барбары Лисков (Liskov Substitution Principle, LSP) является одним из пяти принципов объектно-ориентированного программирования, известных под акронимом SOLID.
Основная идея заключается в том, что если класс
B является подтипом класса A, то объекты класса A могут быть заменены объектами класса B без изменения правильности работы программы. Это означает, что наследование должно использоваться так, чтобы производный класс сохранял поведение базового класса.Производный класс должен соблюдать контракт, определённый базовым классом. Это включает в себя сигнатуры методов и ожидания (предусловия и постусловия).
Инварианты, или неизменяемые условия, которые выполняются для объектов базового класса, должны оставаться в силе и для объектов производного класса.
Производный класс не должен ослаблять постусловия методов базового класса. Постусловия - это условия, которые гарантированы после выполнения метода.
Производный класс не должен усиливать предусловия методов базового класса. Предусловия - это условия, которые должны быть выполнены перед вызовом метода. В этом примере
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
👍13❤2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🔥8
Существует несколько типов данных, которые можно разделить на основные категории: простые типы, ссылочные типы, и пользовательские типы.
Простые типы хранят значения непосредственно и включают примитивные типы, перечисления и структуры.
Целочисленные типы:
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): Тип, представляющий набор именованных констант.
Ссылочные типы хранят ссылку на область памяти, где находятся данные. К ним относятся классы, интерфейсы, делегаты и массивы.
class): Основной строительный блок объектно-ориентированного программирования, могут содержать поля, методы, свойства, события и т.д.
interface): Контракты, определяющие набор методов и свойств, которые должны быть реализованы классами.
delegate): Типы, представляющие ссылку на методы. Используются для реализации обратных вызовов и событий.
event): Механизм, через который объекты могут сообщать о произошедших действиях.
Array): Коллекции элементов одного типа, доступ к которым осуществляется по индексу.
string): Неизменяемые последовательности символов.
Пользовательские типы могут быть созданы на основе простых и ссылочных типов.
Tuple): Группировка значений различных типов.
Типы, созданные для хранения наборов значений, определённых на лету.
Позволяют значимым типам принимать значение
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
👍14❤2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🔥4
Это концепция из теории автоматов и программирования, которая описывает поведение системы на основе различных состояний и переходов между ними. Она позволяет моделировать сложные системы и процессы, управляя переходами между разными состояниями в зависимости от входных данных или событий.
Позволяет разбить сложную логику на более простые, управляемые состояния.
Описывает, как система реагирует на различные события.
Легче понять и изменить поведение системы, когда оно описано в виде состояний и переходов.
Для управления поведением персонажей.
В промышленной автоматике.
Для управления состояниями интерфейсов и переходами между ними.
Для управления последовательностью сообщений и реакцией на них.
using System;
public enum TrafficLightState
{
Red,
Green,
Yellow
}
public class TrafficLight
{
private TrafficLightState _state;
public TrafficLight()
{
_state = TrafficLightState.Red;
}
public void ChangeState()
{
switch (_state)
{
case TrafficLightState.Red:
_state = TrafficLightState.Green;
break;
case TrafficLightState.Green:
_state = TrafficLightState.Yellow;
break;
case TrafficLightState.Yellow:
_state = TrafficLightState.Red;
break;
}
Console.WriteLine($"Состояние светофора: {_state}");
}
}
class Program
{
static void Main()
{
TrafficLight trafficLight = new TrafficLight();
trafficLight.ChangeState(); // Состояние светофора: Green
trafficLight.ChangeState(); // Состояние светофора: Yellow
trafficLight.ChangeState(); // Состояние светофора: Red
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14😁5🤔1👀1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18🔥4
Позволяют определять конструкторы прямо в объявлении класса или структуры, что упрощает код и улучшает его читаемость.
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
👍9