diff --git a/Advanced.Tests/Tasks/LanguagePatternsTasksTests.cs b/Advanced.Tests/Tasks/LanguagePatternsTasksTests.cs
new file mode 100644
index 0000000..26f6f38
--- /dev/null
+++ b/Advanced.Tests/Tasks/LanguagePatternsTasksTests.cs
@@ -0,0 +1,126 @@
+using Advanced.Tasks.LanguagePatterns;
+using Xunit;
+
+namespace Advanced.Tests.Tasks;
+
+public class LanguagePatternsTasksTests
+{
+ private readonly LanguagePatternsTasks _sut = new();
+
+ [Fact]
+ public void GetObjectTypeNull_ReturnsNull()
+ {
+ var result = _sut.GetObjectType(null);
+ Assert.Equal("Null", result);
+ }
+
+ [Fact]
+ public void GetObjectTypeString_ReturnsString()
+ {
+ var result = _sut.GetObjectType("hello");
+ Assert.Equal("String", result);
+ }
+
+ [Fact]
+ public void GetObjectTypeInteger_ReturnsInteger()
+ {
+ var result = _sut.GetObjectType(42);
+ Assert.Equal("Integer", result);
+ }
+
+ [Fact]
+ public void GetObjectTypeBoolean_ReturnsBoolean()
+ {
+ var result = _sut.GetObjectType(true);
+ Assert.Equal("Boolean", result);
+ }
+
+ [Fact]
+ public void GetObjectTypeDouble_ReturnsDouble()
+ {
+ var result = _sut.GetObjectType(3.14);
+ Assert.Equal("Double", result);
+ }
+
+ [Fact]
+ public void GetObjectTypeFloat_ReturnsFloat()
+ {
+ var result = _sut.GetObjectType(2.5f);
+ Assert.Equal("Float", result);
+ }
+
+ [Fact]
+ public void GetObjectTypeUnknownType_ReturnsUnknown()
+ {
+ var result = _sut.GetObjectType(new object());
+ Assert.Equal("Unknown", result);
+ }
+
+ [Fact]
+ public void CalculateShippingCostStandard_ReturnsFixedCost()
+ {
+ var result = _sut.CalculateShippingCost("standard", 10m);
+ Assert.Equal(10m, result);
+ }
+
+ [Fact]
+ public void CalculateShippingCostExpress_ReturnsWeightBasedCost()
+ {
+ var result = _sut.CalculateShippingCost("express", 4m);
+ Assert.Equal(20.0m + 4m * 0.5m, result);
+ }
+
+ [Fact]
+ public void CalculateShippingCostUnknownType_ReturnsZero()
+ {
+ var result = _sut.CalculateShippingCost("rocket", 1m);
+ Assert.Equal(0.0m, result);
+ }
+
+ [Fact]
+ public void CalculateShippingCostNullType_ReturnsZero()
+ {
+ var result = _sut.CalculateShippingCost(null, 1m);
+ Assert.Equal(0.0m, result);
+ }
+
+
+ [Fact]
+ public void GetProductStatusNullProduct_ReturnsInvalidMessage()
+ {
+ var result = _sut.GetProductStatus(null);
+ Assert.Equal("Недопустимый товар", result);
+ }
+
+ [Fact]
+ public void GetProductStatusPriceOver1000_ReturnsExpensive()
+ {
+ var product = new Product { Name = "TV", Price = 1500m, Stock = 5 };
+ var result = _sut.GetProductStatus(product);
+ Assert.Equal("Дорогой товар", result);
+ }
+
+ [Fact]
+ public void GetProductStatusZeroStock_ReturnsOutOfStock()
+ {
+ var product = new Product { Name = "Phone", Price = 800m, Stock = 0 };
+ var result = _sut.GetProductStatus(product);
+ Assert.Equal("Нет в наличии", result);
+ }
+
+ [Fact]
+ public void GetProductStatusNonPositivePrice_ReturnsInvalidPrice()
+ {
+ var product = new Product { Name = "Gift", Price = -10m, Stock = 10 };
+ var result = _sut.GetProductStatus(product);
+ Assert.Equal("Некорректная цена", result);
+ }
+
+ [Fact]
+ public void GetProductStatusValidProduct_ReturnsAvailable()
+ {
+ var product = new Product { Name = "Book", Price = 200m, Stock = 3 };
+ var result = _sut.GetProductStatus(product);
+ Assert.Equal("В наличии", result);
+ }
+}
\ No newline at end of file
diff --git a/Advanced/Tasks/AsyncTasks.cs b/Advanced/Tasks/AsyncTasks.cs
index 9503746..926c43d 100644
--- a/Advanced/Tasks/AsyncTasks.cs
+++ b/Advanced/Tasks/AsyncTasks.cs
@@ -1,47 +1,75 @@
namespace Advanced.Tasks;
+using System.Threading;
+
public class AsyncTasks
{
///
/// Задание 2.1: Напишите асинхронный метод, который имитирует загрузку данных.
/// Используйте Task.Delay для имитации задержки.
///
- public Task LoadDataAsync()
+ public async Task LoadDataAsync()
{
- throw new NotImplementedException();
+ await Task.Delay(1000);
+
+ return "Load data async...";
}
///
/// Задание 2.2: Напишите асинхронный метод, который загружает данные с тайм-аутом.
/// Если операция превышает timeout, бросает TimeoutException.
///
- public Task LoadDataWithTimeoutAsync(TimeSpan timeout)
+ public async Task LoadDataWithTimeoutAsync(TimeSpan timeout)
{
- throw new NotImplementedException();
+ using var cts = new CancellationTokenSource(timeout);
+
+ try
+ {
+ return await LoadDataWithCancellationAsync(cts.Token);
+ }
+ catch (OperationCanceledException) when (cts.Token.IsCancellationRequested)
+ {
+ throw new TimeoutException("Operation timeout");
+ }
}
///
/// Задание 2.3: Напишите метод, который выполняет несколько асинхронных операций параллельно
/// и возвращает результат, когда все завершатся.
///
- public Task ExecuteParallelAsync(IEnumerable> tasks)
+ public async Task ExecuteParallelAsync(IEnumerable> tasks)
{
- throw new NotImplementedException();
+ var taskList = tasks.ToList();
+
+ if (taskList.Count == 0)
+ {
+ return Array.Empty();
+ }
+
+ await Task.WhenAll(taskList);
+
+ return taskList.Select(t => t.Result).ToArray();
}
///
/// Задание 2.4: Напишите метод, который поддерживает отмену операции через CancellationToken.
///
- public Task LoadDataWithCancellationAsync(CancellationToken cancellationToken)
+ public async Task LoadDataWithCancellationAsync(CancellationToken cancellationToken)
{
- throw new NotImplementedException();
+ await Task.Delay(1000, cancellationToken);
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ return "Data loaded...";
}
///
/// Задание 2.5: Напишите метод, который использует ConfigureAwait(false) для избежания deadlock.
///
- public Task LoadDataConfigureAwaitAsync()
+ public async Task LoadDataConfigureAwaitAsync()
{
- throw new NotImplementedException();
+ await Task.Delay(1000).ConfigureAwait(false);
+
+ return "Data loaded...";
}
}
\ No newline at end of file
diff --git a/Advanced/Tasks/GenericsTasks.cs b/Advanced/Tasks/GenericsTasks.cs
index e5efb03..36fa983 100644
--- a/Advanced/Tasks/GenericsTasks.cs
+++ b/Advanced/Tasks/GenericsTasks.cs
@@ -1,5 +1,7 @@
namespace Advanced.Tasks;
+using System.Collections.Generic;
+
public class GenericsTasks
{
///
@@ -7,17 +9,37 @@ public class GenericsTasks
/// Если коллекция пустая, возвращает default значение типа.
/// В каждом задании используйте async/await.
///
- public T GetFirstElement(IEnumerable collection)
+ public T? GetFirstElement(IEnumerable? collection)
{
- throw new NotImplementedException();
+ if (collection == null)
+ {
+ return default(T);
+ }
+
+ foreach (var item in collection)
+ {
+ return item;
+ }
+
+ return default(T);
}
///
/// Задание 1.2: Напишите generic метод, который фильтрует коллекцию по предикату.
///
- public IEnumerable Filter(IEnumerable collection, Func predicate)
+ public IEnumerable Filter(IEnumerable? collection, Func? predicate)
{
- throw new NotImplementedException();
+ if (collection == null)
+ {
+ return Enumerable.Empty();
+ }
+
+ if (predicate == null)
+ {
+ return collection;
+ }
+
+ return collection.Where(predicate);
}
///
@@ -25,7 +47,7 @@ public IEnumerable Filter(IEnumerable collection, Func predica
///
public void Swap(ref T a, ref T b)
{
- throw new NotImplementedException();
+ (a, b) = (b, a);
}
///
diff --git a/Advanced/Tasks/LanguagePatterns/DemonstrateDeconstruction.cs b/Advanced/Tasks/LanguagePatterns/DemonstrateDeconstruction.cs
new file mode 100644
index 0000000..663b63b
--- /dev/null
+++ b/Advanced/Tasks/LanguagePatterns/DemonstrateDeconstruction.cs
@@ -0,0 +1,10 @@
+namespace Advanced.Tasks.LanguagePatterns;
+
+public class DemonstrateDeconstruction
+{
+ public void Example()
+ {
+ var name = new FullName("Евгений", "Березин");
+ var (first, last) = name;
+ }
+}
\ No newline at end of file
diff --git a/Advanced/Tasks/LanguagePatterns/FullName.cs b/Advanced/Tasks/LanguagePatterns/FullName.cs
new file mode 100644
index 0000000..fe95a73
--- /dev/null
+++ b/Advanced/Tasks/LanguagePatterns/FullName.cs
@@ -0,0 +1,3 @@
+namespace Advanced.Tasks.LanguagePatterns;
+
+public record FullName(string FirstName, string LastName);
\ No newline at end of file
diff --git a/Advanced/Tasks/LanguagePatterns/IComparable.cs b/Advanced/Tasks/LanguagePatterns/IComparable.cs
new file mode 100644
index 0000000..69f3f8f
--- /dev/null
+++ b/Advanced/Tasks/LanguagePatterns/IComparable.cs
@@ -0,0 +1,6 @@
+namespace Advanced.Tasks.LanguagePatterns;
+
+public interface IComparable
+{
+ int CompareTo(T compare);
+}
\ No newline at end of file
diff --git a/Advanced/Tasks/LanguagePatterns/LanguagePatternsTasks.cs b/Advanced/Tasks/LanguagePatterns/LanguagePatternsTasks.cs
index 123632a..4bfce9c 100644
--- a/Advanced/Tasks/LanguagePatterns/LanguagePatternsTasks.cs
+++ b/Advanced/Tasks/LanguagePatterns/LanguagePatternsTasks.cs
@@ -8,39 +8,54 @@ public class LanguagePatternsTasks
///
/// Задание 4.1: Создайте record Person с свойствами Name и Age.
///
-
-
///
/// Задание 4.2: Создайте класс Product с init-only свойствами.
///
-
-
///
/// Задание 4.3: Используйте pattern matching для определения типа объекта.
///
- public string GetObjectType(object obj)
+ public string GetObjectType(object? obj)
{
- throw new NotImplementedException();
+ return obj switch
+ {
+ null => "Null",
+ string => "String",
+ int => "Integer",
+ bool => "Boolean",
+ double => "Double",
+ float => "Float",
+ _ => "Unknown"
+ };
}
///
/// Задание 4.4: Используйте switch expression для вычисления стоимости доставки.
///
- public decimal CalculateShippingCost(string shippingType, decimal weight)
+ public decimal CalculateShippingCost(string? shippingType, decimal weight)
{
- throw new NotImplementedException();
+ return shippingType?.ToLowerInvariant() switch
+ {
+ "standard" => 10m,
+ "express" => 20.0m + weight * 0.5m,
+ _ => 0.0m
+ };
}
///
/// Задание 4.5: Создайте record и напишите код (в отдельном классе DemonstrateDeconstruction) использования деконструкции.
///
-
-
///
/// Задание 4.6: Используйте property patterns класса Product для проверки условий.
///
- public string GetProductStatus(Product product)
+ public string GetProductStatus(Product? product)
{
- throw new NotImplementedException();
+ return product switch
+ {
+ null => "Недопустимый товар",
+ { Price: > 1000 } => "Дорогой товар",
+ { Stock: 0 } => "Нет в наличии",
+ { Price: <= 0 } => "Некорректная цена",
+ _ => "В наличии"
+ };
}
}
\ No newline at end of file
diff --git a/Advanced/Tasks/LanguagePatterns/Person.cs b/Advanced/Tasks/LanguagePatterns/Person.cs
new file mode 100644
index 0000000..f44ee1b
--- /dev/null
+++ b/Advanced/Tasks/LanguagePatterns/Person.cs
@@ -0,0 +1,6 @@
+namespace Advanced.Tasks.LanguagePatterns;
+
+///
+/// Задание 4.1: record Person с Name и Age.
+///
+public record Person(string Name, int Age);
\ No newline at end of file
diff --git a/Advanced/Tasks/LanguagePatterns/Product.cs b/Advanced/Tasks/LanguagePatterns/Product.cs
new file mode 100644
index 0000000..1317f2b
--- /dev/null
+++ b/Advanced/Tasks/LanguagePatterns/Product.cs
@@ -0,0 +1,11 @@
+namespace Advanced.Tasks.LanguagePatterns;
+
+///
+/// Задание 4.2: Класс Product с init-only свойствами.
+///
+public class Product
+{
+ public string? Name { get; init; }
+ public decimal Price { get; init; }
+ public int Stock { get; init; }
+}
\ No newline at end of file
diff --git a/Advanced/Tasks/PerformanceTasks.cs b/Advanced/Tasks/PerformanceTasks.cs
index f24c359..f939875 100644
--- a/Advanced/Tasks/PerformanceTasks.cs
+++ b/Advanced/Tasks/PerformanceTasks.cs
@@ -7,7 +7,7 @@ public class PerformanceTasks
///
public void ReverseArray(T[] array)
{
- throw new NotImplementedException();
+ array.AsSpan().Reverse();
}
///
@@ -15,7 +15,14 @@ public void ReverseArray(T[] array)
///
public int SumArray(Span span)
{
- throw new NotImplementedException();
+ int sum = 0;
+
+ foreach (int item in span)
+ {
+ sum += item;
+ }
+
+ return sum;
}
///
@@ -23,11 +30,11 @@ public int SumArray(Span span)
///
public object BoxValue(int value)
{
- throw new NotImplementedException();
+ return value;
}
public int UnboxValue(object value)
{
- throw new NotImplementedException();
+ return (int)value;
}
}
\ No newline at end of file