mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 10:34:30 +08:00
refactor(pipe): 重构函数式编程扩展方法为模块化结构
- 将原有的PipeExtensionsTests拆分为多个专门的测试类 - 创建ControlExtensionsTests用于控制流函数测试 - 创建EnumerableExtensionsTests用于集合操作函数测试 - 创建FunctionExtensionsTests用于高级函数操作测试 - 移除旧的综合测试文件中的多余测试方法 - 更新文档结构以反映新的模块化组织方式 - 重新整理README.md文档为模块化分类说明
This commit is contained in:
parent
5318f5a38f
commit
43dcae0cf5
@ -0,0 +1,72 @@
|
||||
using GFramework.Core.functional.collections;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace GFramework.Core.Tests.functional.collections;
|
||||
|
||||
/// <summary>
|
||||
/// EnumerableExtensions扩展方法测试类,用于验证集合函数式编程扩展方法的正确性
|
||||
/// 包括Map、Filter、Reduce等集合操作功能的测试
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class EnumerableExtensionsTests
|
||||
{
|
||||
#region Map Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Map方法 - 验证集合中的每个元素都能被正确转换
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Map_Should_Transform_Each_Element_In_Collection()
|
||||
{
|
||||
// Arrange
|
||||
var numbers = new[] {1, 2, 3, 4};
|
||||
|
||||
// Act
|
||||
var result = numbers.Map(x => x * x).ToArray();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EquivalentTo([1, 4, 9, 16]));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Filter Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Filter方法 - 验证集合能够根据条件正确过滤
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Filter_Should_Filter_Elements_Based_On_Predicate()
|
||||
{
|
||||
// Arrange
|
||||
var numbers = new[] {1, 2, 3, 4, 5, 6};
|
||||
|
||||
// Act
|
||||
var result = numbers.Filter(x => x % 2 == 0).ToArray();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EquivalentTo([2, 4, 6]));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Reduce Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Reduce方法 - 验证集合能够正确归约为单个值
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Reduce_Should_Reduce_Collection_To_Single_Value()
|
||||
{
|
||||
// Arrange
|
||||
var numbers = new[] {1, 2, 3, 4};
|
||||
|
||||
// Act
|
||||
var result = numbers.Reduce(0, (acc, x) => acc + x);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(10));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -0,0 +1,229 @@
|
||||
using GFramework.Core.functional.control;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace GFramework.Core.Tests.functional.control;
|
||||
|
||||
/// <summary>
|
||||
/// ControlExtensions扩展方法测试类,用于验证控制流函数式编程扩展方法的正确性
|
||||
/// 包括模式匹配、条件执行等控制流功能的测试
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class ControlExtensionsTests
|
||||
{
|
||||
#region Match Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Match方法 - 验证模式匹配功能
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Match_Should_Execute_Matching_Case()
|
||||
{
|
||||
// Arrange
|
||||
var value = 5;
|
||||
|
||||
// Act
|
||||
var result = value.Match(
|
||||
(x => x < 0, _ => "negative"),
|
||||
(x => x > 0, _ => "positive"),
|
||||
(x => x == 0, _ => "zero")
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo("positive"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试Match方法 - 验证无匹配时抛出异常
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Match_Should_Throw_Exception_When_No_Case_Matches()
|
||||
{
|
||||
// Arrange
|
||||
var value = 10;
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
value.Match(
|
||||
(x => x < 0, _ => "negative"),
|
||||
(x => x > 10, _ => "large positive")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MatchOrDefault Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试MatchOrDefault方法 - 验证模式匹配带默认值功能
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void MatchOrDefault_Should_Execute_Matching_Case_Or_Return_Default()
|
||||
{
|
||||
// Arrange
|
||||
var value = 10;
|
||||
|
||||
// Act
|
||||
var result = value.MatchOrDefault("unknown",
|
||||
(x => x < 0, _ => "negative"),
|
||||
(x => x > 10, _ => "large positive")
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo("unknown"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region If Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试If方法 - 验证条件执行功能
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void If_Should_Execute_ThenFunc_When_Condition_Is_True()
|
||||
{
|
||||
// Arrange
|
||||
var value = 5;
|
||||
|
||||
// Act
|
||||
var result = value.If(x => x > 0, x => x * 2);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(10));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试If方法 - 验证条件为假时不执行转换函数
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void If_Should_Return_Original_Value_When_Condition_Is_False()
|
||||
{
|
||||
// Arrange
|
||||
var value = -5;
|
||||
|
||||
// Act
|
||||
var result = value.If(x => x > 0, x => x * 2);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(-5));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IfElse Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试IfElse方法 - 验证条件分支功能
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void IfElse_Should_Execute_ThenFunc_When_Condition_Is_True()
|
||||
{
|
||||
// Arrange
|
||||
var value = 5;
|
||||
|
||||
// Act
|
||||
var result = value.IfElse(
|
||||
x => x > 0,
|
||||
x => x * 2,
|
||||
x => x * -1
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(10));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试IfElse方法 - 验证条件为假时执行else分支
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void IfElse_Should_Execute_ElseFunc_When_Condition_Is_False()
|
||||
{
|
||||
// Arrange
|
||||
var value = -5;
|
||||
|
||||
// Act
|
||||
var result = value.IfElse(
|
||||
x => x > 0,
|
||||
x => x * 2,
|
||||
x => x * -1
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(5));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region TakeIf Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试TakeIf方法 - 验证条件为真时返回原值
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TakeIf_Should_Return_Value_When_Condition_Is_True()
|
||||
{
|
||||
// Arrange
|
||||
string str = "Hello";
|
||||
|
||||
// Act
|
||||
var result = str.TakeIf(s => s.Length > 3);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo("Hello"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试TakeIf方法 - 验证条件为假时返回null
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TakeIf_Should_Return_Null_When_Condition_Is_False()
|
||||
{
|
||||
// Arrange
|
||||
string str = "Hi";
|
||||
|
||||
// Act
|
||||
var result = str.TakeIf(s => s.Length > 3);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region TakeUnless Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试TakeUnless方法 - 验证条件为假时返回原值
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TakeUnless_Should_Return_Value_When_Condition_Is_False()
|
||||
{
|
||||
// Arrange
|
||||
string str = "Hi";
|
||||
|
||||
// Act
|
||||
var result = str.TakeUnless(s => s.Length > 3);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo("Hi"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试TakeUnless方法 - 验证条件为真时返回null
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TakeUnless_Should_Return_Null_When_Condition_Is_True()
|
||||
{
|
||||
// Arrange
|
||||
string str = "Hello";
|
||||
|
||||
// Act
|
||||
var result = str.TakeUnless(s => s.Length > 3);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -0,0 +1,172 @@
|
||||
using GFramework.Core.functional.functions;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace GFramework.Core.Tests.functional.functions;
|
||||
|
||||
/// <summary>
|
||||
/// FunctionExtensions扩展方法测试类,用于验证高级函数式编程扩展方法的正确性
|
||||
/// 包括柯里化、偏函数应用、重复执行、安全执行和缓存等功能的测试
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class FunctionExtensionsTests
|
||||
{
|
||||
#region Curry Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Curry方法 - 验证二参数函数能够正确柯里化
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Curry_Should_Convert_Binary_Function_To_Curried_Form()
|
||||
{
|
||||
// Arrange
|
||||
Func<int, int, int> add = (x, y) => x + y;
|
||||
|
||||
// Act
|
||||
var curriedAdd = add.Curry();
|
||||
var addFive = curriedAdd(5);
|
||||
var result = addFive(3);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(8));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Uncurry Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Uncurry方法 - 验证柯里化函数能够正确还原为二参数函数
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Uncurry_Should_Convert_Curried_Function_Back_To_Binary_Form()
|
||||
{
|
||||
// Arrange
|
||||
Func<int, int, int> originalAdd = (x, y) => x + y;
|
||||
var curriedAdd = originalAdd.Curry();
|
||||
|
||||
// Act
|
||||
var uncurriedAdd = curriedAdd.Uncurry();
|
||||
var result = uncurriedAdd(5, 3);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(8));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Partial Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Partial方法 - 验证部分应用函数功能
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Partial_Should_Fix_First_Argument_Of_Binary_Function()
|
||||
{
|
||||
// Arrange
|
||||
Func<int, int, int> multiply = (x, y) => x * y;
|
||||
|
||||
// Act
|
||||
var doubleFunction = multiply.Partial(2);
|
||||
var result = doubleFunction(5);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(10));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Repeat Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Repeat方法 - 验证重复执行函数功能
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Repeat_Should_Execute_Function_N_Times()
|
||||
{
|
||||
// Arrange
|
||||
var initialValue = 2;
|
||||
|
||||
// Act
|
||||
var result = initialValue.Repeat(3, x => x * 2);
|
||||
|
||||
// Assert
|
||||
// 2 -> 4 -> 8 -> 16 (3次重复)
|
||||
Assert.That(result, Is.EqualTo(16));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Try Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Try方法 - 验证安全执行成功情况
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Try_Should_Return_Success_When_Function_Does_Not_Throw()
|
||||
{
|
||||
// Arrange
|
||||
var value = 10;
|
||||
|
||||
// Act
|
||||
var (success, result, error) = value.Try(x => 100 / x);
|
||||
|
||||
// Assert
|
||||
Assert.That(success, Is.True);
|
||||
Assert.That(result, Is.EqualTo(10));
|
||||
Assert.That(error, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试Try方法 - 验证安全执行异常情况
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Try_Should_Return_Failure_When_Function_Throws()
|
||||
{
|
||||
// Arrange
|
||||
var value = 0;
|
||||
|
||||
// Act
|
||||
var (success, result, error) = value.Try(x => 100 / x);
|
||||
|
||||
// Assert
|
||||
Assert.That(success, Is.False);
|
||||
Assert.That(result, Is.EqualTo(0)); // 对于int类型,默认值是0
|
||||
Assert.That(error, Is.Not.Null);
|
||||
Assert.That(error, Is.TypeOf<DivideByZeroException>());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Memoize Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Memoize方法 - 验证函数结果缓存功能
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Memoize_Should_Cache_Function_Results()
|
||||
{
|
||||
// Arrange
|
||||
var callCount = 0;
|
||||
Func<int, int> expensiveFunction = x =>
|
||||
{
|
||||
callCount++;
|
||||
return x * x;
|
||||
};
|
||||
var memoized = expensiveFunction.Memoize();
|
||||
|
||||
// Act
|
||||
var result1 = memoized(5); // 第一次调用
|
||||
var result2 = memoized(5); // 第二次调用,应该使用缓存
|
||||
var result3 = memoized(3); // 新参数,应该调用函数
|
||||
var result4 = memoized(3); // 再次使用相同参数,应该使用缓存
|
||||
|
||||
// Assert
|
||||
Assert.That(result1, Is.EqualTo(25));
|
||||
Assert.That(result2, Is.EqualTo(25));
|
||||
Assert.That(result3, Is.EqualTo(9));
|
||||
Assert.That(result4, Is.EqualTo(9));
|
||||
Assert.That(callCount, Is.EqualTo(2)); // 只应调用两次,而不是四次
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -1,12 +1,11 @@
|
||||
using GFramework.Core.extensions;
|
||||
using GFramework.Core.functional.pipe;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace GFramework.Core.Tests.functional.pipe;
|
||||
|
||||
/// <summary>
|
||||
/// PipeExtensions扩展方法测试类,用于验证函数式编程扩展方法的正确性
|
||||
/// 包括管道操作、函数组合、柯里化、模式匹配等多种函数式编程功能的测试
|
||||
/// PipeExtensions扩展方法测试类,用于验证管道和函数组合扩展方法的正确性
|
||||
/// 包括管道操作、函数组合等核心功能的测试
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class PipeExtensionsTests
|
||||
@ -101,66 +100,6 @@ public class PipeExtensionsTests
|
||||
|
||||
#endregion
|
||||
|
||||
#region Map Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Map方法 - 验证集合中的每个元素都能被正确转换
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Map_Should_Transform_Each_Element_In_Collection()
|
||||
{
|
||||
// Arrange
|
||||
var numbers = new[] {1, 2, 3, 4};
|
||||
|
||||
// Act
|
||||
var result = numbers.Map(x => x * x).ToArray();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EquivalentTo([1, 4, 9, 16]));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Filter Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Filter方法 - 验证集合能够根据条件正确过滤
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Filter_Should_Filter_Elements_Based_On_Predicate()
|
||||
{
|
||||
// Arrange
|
||||
var numbers = new[] {1, 2, 3, 4, 5, 6};
|
||||
|
||||
// Act
|
||||
var result = numbers.Filter(x => x % 2 == 0).ToArray();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EquivalentTo([2, 4, 6]));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Reduce Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Reduce方法 - 验证集合能够正确归约为单个值
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Reduce_Should_Reduce_Collection_To_Single_Value()
|
||||
{
|
||||
// Arrange
|
||||
var numbers = new[] {1, 2, 3, 4};
|
||||
|
||||
// Act
|
||||
var result = numbers.Reduce(0, (acc, x) => acc + x);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(10));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Apply Tests
|
||||
|
||||
/// <summary>
|
||||
@ -181,272 +120,6 @@ public class PipeExtensionsTests
|
||||
|
||||
#endregion
|
||||
|
||||
#region Curry Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Curry方法 - 验证二参数函数能够正确柯里化
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Curry_Should_Convert_Binary_Function_To_Curried_Form()
|
||||
{
|
||||
// Arrange
|
||||
Func<int, int, int> add = (x, y) => x + y;
|
||||
|
||||
// Act
|
||||
var curriedAdd = add.Curry();
|
||||
var addFive = curriedAdd(5);
|
||||
var result = addFive(3);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(8));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Uncurry Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Uncurry方法 - 验证柯里化函数能够正确还原为二参数函数
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Uncurry_Should_Convert_Curried_Function_Back_To_Binary_Form()
|
||||
{
|
||||
// Arrange
|
||||
Func<int, int, int> originalAdd = (x, y) => x + y;
|
||||
var curriedAdd = originalAdd.Curry();
|
||||
|
||||
// Act
|
||||
var uncurriedAdd = curriedAdd.Uncurry();
|
||||
var result = uncurriedAdd(5, 3);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(8));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Partial Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Partial方法 - 验证部分应用函数功能
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Partial_Should_Fix_First_Argument_Of_Binary_Function()
|
||||
{
|
||||
// Arrange
|
||||
Func<int, int, int> multiply = (x, y) => x * y;
|
||||
|
||||
// Act
|
||||
var doubleFunction = multiply.Partial(2);
|
||||
var result = doubleFunction(5);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(10));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Match Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Match方法 - 验证模式匹配功能
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Match_Should_Execute_Matching_Case()
|
||||
{
|
||||
// Arrange
|
||||
var value = 5;
|
||||
|
||||
// Act
|
||||
var result = value.Match(
|
||||
(x => x < 0, _ => "negative"),
|
||||
(x => x > 0, _ => "positive"),
|
||||
(x => x == 0, _ => "zero")
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo("positive"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试Match方法 - 验证无匹配时抛出异常
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Match_Should_Throw_Exception_When_No_Case_Matches()
|
||||
{
|
||||
// Arrange
|
||||
var value = 10;
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
value.Match(
|
||||
(x => x < 0, _ => "negative"),
|
||||
(x => x > 10, _ => "large positive")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MatchOrDefault Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试MatchOrDefault方法 - 验证模式匹配带默认值功能
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void MatchOrDefault_Should_Execute_Matching_Case_Or_Return_Default()
|
||||
{
|
||||
// Arrange
|
||||
var value = 10;
|
||||
|
||||
// Act
|
||||
var result = value.MatchOrDefault("unknown",
|
||||
(x => x < 0, _ => "negative"),
|
||||
(x => x > 10, _ => "large positive")
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo("unknown"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region If Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试If方法 - 验证条件执行功能
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void If_Should_Execute_ThenFunc_When_Condition_Is_True()
|
||||
{
|
||||
// Arrange
|
||||
var value = 5;
|
||||
|
||||
// Act
|
||||
var result = value.If(x => x > 0, x => x * 2);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(10));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试If方法 - 验证条件为假时不执行转换函数
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void If_Should_Return_Original_Value_When_Condition_Is_False()
|
||||
{
|
||||
// Arrange
|
||||
var value = -5;
|
||||
|
||||
// Act
|
||||
var result = value.If(x => x > 0, x => x * 2);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(-5));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IfElse Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试IfElse方法 - 验证条件分支功能
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void IfElse_Should_Execute_ThenFunc_When_Condition_Is_True()
|
||||
{
|
||||
// Arrange
|
||||
var value = 5;
|
||||
|
||||
// Act
|
||||
var result = value.IfElse(
|
||||
x => x > 0,
|
||||
x => x * 2,
|
||||
x => x * -1
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(10));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试IfElse方法 - 验证条件为假时执行else分支
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void IfElse_Should_Execute_ElseFunc_When_Condition_Is_False()
|
||||
{
|
||||
// Arrange
|
||||
var value = -5;
|
||||
|
||||
// Act
|
||||
var result = value.IfElse(
|
||||
x => x > 0,
|
||||
x => x * 2,
|
||||
x => x * -1
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(5));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region As Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试As方法 - 验证安全类型转换功能
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void As_Should_Perform_Safe_Type_Cast()
|
||||
{
|
||||
// Arrange
|
||||
object obj = "Hello";
|
||||
|
||||
// Act
|
||||
var result = obj.As<string>();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo("Hello"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试As方法 - 验证不兼容类型转换返回null
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void As_Should_Return_Null_For_Incompatible_Types()
|
||||
{
|
||||
// Arrange
|
||||
object obj = 42;
|
||||
|
||||
// Act
|
||||
var result = obj.As<string>();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Cast Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Cast方法 - 验证强制类型转换功能
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Cast_Should_Perform_Forced_Type_Cast()
|
||||
{
|
||||
// Arrange
|
||||
object obj = "Hello";
|
||||
|
||||
// Act
|
||||
var result = obj.Cast<string>();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo("Hello"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Also Tests
|
||||
|
||||
/// <summary>
|
||||
@ -488,171 +161,4 @@ public class PipeExtensionsTests
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region TakeIf Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试TakeIf方法 - 验证条件为真时返回原值
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TakeIf_Should_Return_Value_When_Condition_Is_True()
|
||||
{
|
||||
// Arrange
|
||||
string str = "Hello";
|
||||
|
||||
// Act
|
||||
var result = str.TakeIf(s => s.Length > 3);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo("Hello"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试TakeIf方法 - 验证条件为假时返回null
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TakeIf_Should_Return_Null_When_Condition_Is_False()
|
||||
{
|
||||
// Arrange
|
||||
string str = "Hi";
|
||||
|
||||
// Act
|
||||
var result = str.TakeIf(s => s.Length > 3);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region TakeUnless Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试TakeUnless方法 - 验证条件为假时返回原值
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TakeUnless_Should_Return_Value_When_Condition_Is_False()
|
||||
{
|
||||
// Arrange
|
||||
string str = "Hi";
|
||||
|
||||
// Act
|
||||
var result = str.TakeUnless(s => s.Length > 3);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo("Hi"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试TakeUnless方法 - 验证条件为真时返回null
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TakeUnless_Should_Return_Null_When_Condition_Is_True()
|
||||
{
|
||||
// Arrange
|
||||
string str = "Hello";
|
||||
|
||||
// Act
|
||||
var result = str.TakeUnless(s => s.Length > 3);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Repeat Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Repeat方法 - 验证重复执行函数功能
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Repeat_Should_Execute_Function_N_Times()
|
||||
{
|
||||
// Arrange
|
||||
var initialValue = 2;
|
||||
|
||||
// Act
|
||||
var result = initialValue.Repeat(3, x => x * 2);
|
||||
|
||||
// Assert
|
||||
// 2 -> 4 -> 8 -> 16 (3次重复)
|
||||
Assert.That(result, Is.EqualTo(16));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Try Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Try方法 - 验证安全执行成功情况
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Try_Should_Return_Success_When_Function_Does_Not_Throw()
|
||||
{
|
||||
// Arrange
|
||||
var value = 10;
|
||||
|
||||
// Act
|
||||
var (success, result, error) = value.Try(x => 100 / x);
|
||||
|
||||
// Assert
|
||||
Assert.That(success, Is.True);
|
||||
Assert.That(result, Is.EqualTo(10));
|
||||
Assert.That(error, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试Try方法 - 验证安全执行异常情况
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Try_Should_Return_Failure_When_Function_Throws()
|
||||
{
|
||||
// Arrange
|
||||
var value = 0;
|
||||
|
||||
// Act
|
||||
var (success, result, error) = value.Try(x => 100 / x);
|
||||
|
||||
// Assert
|
||||
Assert.That(success, Is.False);
|
||||
Assert.That(result, Is.EqualTo(0)); // 对于int类型,默认值是0
|
||||
Assert.That(error, Is.Not.Null);
|
||||
Assert.That(error, Is.TypeOf<DivideByZeroException>());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Memoize Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Memoize方法 - 验证函数结果缓存功能
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Memoize_Should_Cache_Function_Results()
|
||||
{
|
||||
// Arrange
|
||||
var callCount = 0;
|
||||
Func<int, int> expensiveFunction = x =>
|
||||
{
|
||||
callCount++;
|
||||
return x * x;
|
||||
};
|
||||
var memoized = expensiveFunction.Memoize();
|
||||
|
||||
// Act
|
||||
var result1 = memoized(5); // 第一次调用
|
||||
var result2 = memoized(5); // 第二次调用,应该使用缓存
|
||||
var result3 = memoized(3); // 新参数,应该调用函数
|
||||
var result4 = memoized(3); // 再次使用相同参数,应该使用缓存
|
||||
|
||||
// Assert
|
||||
Assert.That(result1, Is.EqualTo(25));
|
||||
Assert.That(result2, Is.EqualTo(25));
|
||||
Assert.That(result3, Is.EqualTo(9));
|
||||
Assert.That(result4, Is.EqualTo(9));
|
||||
Assert.That(callCount, Is.EqualTo(2)); // 只应调用两次,而不是四次
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
using GFramework.Core.extensions;
|
||||
using GFramework.Core.functional.types;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace GFramework.Core.Tests.functional.types;
|
||||
|
||||
/// <summary>
|
||||
/// TypeExtensions扩展方法测试类,用于验证类型转换相关扩展方法的正确性
|
||||
/// 包括安全类型转换和强制类型转换功能的测试
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class TypeExtensionsTests
|
||||
{
|
||||
#region As Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试As方法 - 验证安全类型转换功能
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void As_Should_Perform_Safe_Type_Cast()
|
||||
{
|
||||
// Arrange
|
||||
object obj = "Hello";
|
||||
|
||||
// Act
|
||||
var result = obj.As<string>();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo("Hello"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试As方法 - 验证不兼容类型转换返回null
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void As_Should_Return_Null_For_Incompatible_Types()
|
||||
{
|
||||
// Arrange
|
||||
object obj = 42;
|
||||
|
||||
// Act
|
||||
var result = obj.As<string>();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Cast Tests
|
||||
|
||||
/// <summary>
|
||||
/// 测试Cast方法 - 验证强制类型转换功能
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Cast_Should_Perform_Forced_Type_Cast()
|
||||
{
|
||||
// Arrange
|
||||
object obj = "Hello";
|
||||
|
||||
// Act
|
||||
var result = obj.Cast<string>();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo("Hello"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -1,20 +1,24 @@
|
||||
# Pipe Extensions - 函数式编程扩展方法
|
||||
# Functional Extensions - 函数式编程扩展方法
|
||||
|
||||
提供了一系列用于函数式编程的管道和组合操作扩展方法。
|
||||
提供了一系列用于函数式编程的扩展方法,已按功能拆分为多个类别。
|
||||
|
||||
## 功能概览
|
||||
|
||||
这些扩展方法实现了函数式编程的核心概念,包括管道操作、函数组合、柯里化、模式匹配等功能,使C#代码更加简洁和函数式。
|
||||
这些扩展方法实现了函数式编程的核心概念,包括管道操作、函数组合、集合操作、控制流、类型转换等功能,使C#代码更加简洁和函数式。
|
||||
|
||||
## 方法列表及用法
|
||||
## 模块分类
|
||||
|
||||
### 1. Pipe - 管道操作
|
||||
### 1. Pipe Extensions - 管道和函数组合操作
|
||||
位于 `GFramework.Core.functional.pipe` 命名空间,提供管道和函数组合操作。
|
||||
|
||||
#### 方法列表及用法:
|
||||
- **Pipe** - 把值送进函数
|
||||
```csharp
|
||||
// 将值传入函数进行处理
|
||||
var result = 5.Pipe(x => x * 2); // 结果为 10
|
||||
```
|
||||
|
||||
### 2. Then - 函数组合
|
||||
- **Then** - 函数组合(f1.Then(f2))
|
||||
```csharp
|
||||
// 组合两个函数,先执行first再执行second
|
||||
Func<int, int> addTwo = x => x + 2;
|
||||
@ -23,7 +27,7 @@ var composed = addTwo.Then(multiplyByThree); // 先+2再*3
|
||||
var result = composed(5); // (5+2)*3 = 21
|
||||
```
|
||||
|
||||
### 3. After - 反向组合
|
||||
- **After** - 反向函数组合
|
||||
```csharp
|
||||
// 与Then相反,以不同的顺序组合函数
|
||||
Func<int, int> multiplyByThree = x => x * 3;
|
||||
@ -32,66 +36,61 @@ var composed = multiplyByThree.After(addTwo); // 先+2再*3
|
||||
var result = composed(5); // (5+2)*3 = 21
|
||||
```
|
||||
|
||||
### 4. Tap - 执行副作用
|
||||
- **Tap** - 执行副作用操作但返回原值
|
||||
```csharp
|
||||
// 执行副作用操作但返回原值,常用于调试或日志记录
|
||||
var value = 42.Tap(Console.WriteLine); // 输出42,但value仍为42
|
||||
```
|
||||
|
||||
### 5. Map - 映射操作
|
||||
```csharp
|
||||
// 对集合中的每个元素应用函数
|
||||
var numbers = new[] {1, 2, 3, 4};
|
||||
var squared = numbers.Map(x => x * x); // {1, 4, 9, 16}
|
||||
```
|
||||
|
||||
### 6. Filter - 过滤操作
|
||||
```csharp
|
||||
// 过滤集合中的元素
|
||||
var numbers = new[] {1, 2, 3, 4, 5, 6};
|
||||
var evens = numbers.Filter(x => x % 2 == 0); // {2, 4, 6}
|
||||
```
|
||||
|
||||
### 7. Reduce - 归约操作
|
||||
```csharp
|
||||
// 将集合归约为单个值
|
||||
var numbers = new[] {1, 2, 3, 4};
|
||||
var sum = numbers.Reduce(0, (acc, x) => acc + x); // 10
|
||||
```
|
||||
|
||||
### 8. Apply - 应用函数
|
||||
- **Apply** - 将函数应用于值
|
||||
```csharp
|
||||
// 将参数应用于函数
|
||||
Func<int, int> multiplyByTwo = x => x * 2;
|
||||
var result = multiplyByTwo.Apply(5); // 10
|
||||
```
|
||||
|
||||
### 9. Curry - 柯里化
|
||||
- **Also** - 执行操作并返回原值
|
||||
```csharp
|
||||
// 将多参数函数转换为链式单参数函数
|
||||
Func<int, int, int> add = (x, y) => x + y;
|
||||
var curriedAdd = add.Curry(); // 返回 Func<int, Func<int, int>>
|
||||
var addFive = curriedAdd(5); // 返回 Func<int, int>
|
||||
var result = addFive(3); // 8
|
||||
// 执行操作并返回原值
|
||||
var value = 42.Also(Console.WriteLine); // 输出42,返回42
|
||||
```
|
||||
|
||||
### 10. Uncurry - 取消柯里化
|
||||
- **Let** - 将值转换为另一个值
|
||||
```csharp
|
||||
// 将柯里化函数转换回多参数函数
|
||||
var curriedAdd = ((Func<int, int, int>)((x, y) => x + y)).Curry();
|
||||
var uncurriedAdd = curriedAdd.Uncurry(); // 返回 Func<int, int, int>
|
||||
var result = uncurriedAdd(5, 3); // 8
|
||||
// 转换值
|
||||
var result = 5.Let(x => x * 2); // 10
|
||||
```
|
||||
|
||||
### 11. Partial - 部分应用
|
||||
### 2. Collections Extensions - 集合操作
|
||||
位于 `GFramework.Core.functional.collections` 命名空间,提供对集合的函数式操作。
|
||||
|
||||
#### 方法列表及用法:
|
||||
- **Map** - 映射操作
|
||||
```csharp
|
||||
// 固定函数的部分参数
|
||||
Func<int, int, int> multiply = (x, y) => x * y;
|
||||
var double = multiply.Partial(2); // 固定第一个参数为2
|
||||
var result = double(5); // 10
|
||||
// 对集合中的每个元素应用函数
|
||||
var numbers = new[] {1, 2, 3, 4};
|
||||
var squared = numbers.Map(x => x * x); // {1, 4, 9, 16}
|
||||
```
|
||||
|
||||
### 12. Match - 模式匹配
|
||||
- **Filter** - 过滤操作
|
||||
```csharp
|
||||
// 过滤集合中的元素
|
||||
var numbers = new[] {1, 2, 3, 4, 5, 6};
|
||||
var evens = numbers.Filter(x => x % 2 == 0); // {2, 4, 6}
|
||||
```
|
||||
|
||||
- **Reduce** - 归约操作
|
||||
```csharp
|
||||
// 将集合归约为单个值
|
||||
var numbers = new[] {1, 2, 3, 4};
|
||||
var sum = numbers.Reduce(0, (acc, x) => acc + x); // 10
|
||||
```
|
||||
|
||||
### 3. Control Extensions - 控制流操作
|
||||
位于 `GFramework.Core.functional.control` 命名空间,提供函数式风格的控制结构。
|
||||
|
||||
#### 方法列表及用法:
|
||||
- **Match** - 模式匹配
|
||||
```csharp
|
||||
// 基于条件的模式匹配
|
||||
var result = 5.Match(
|
||||
@ -101,7 +100,7 @@ var result = 5.Match(
|
||||
); // "正数"
|
||||
```
|
||||
|
||||
### 13. MatchOrDefault - 带默认值的模式匹配
|
||||
- **MatchOrDefault** - 带默认值的模式匹配
|
||||
```csharp
|
||||
// 模式匹配,无匹配时返回默认值
|
||||
var result = 0.MatchOrDefault("未知数字",
|
||||
@ -110,7 +109,7 @@ var result = 0.MatchOrDefault("未知数字",
|
||||
); // "未知数字"
|
||||
```
|
||||
|
||||
### 14. If / IfElse - 条件执行
|
||||
- **If / IfElse** - 条件执行
|
||||
```csharp
|
||||
// 条件执行操作
|
||||
var result = 5.If(x => x > 0, x => x * 2); // 10 (因为5>0,所以乘以2)
|
||||
@ -121,24 +120,7 @@ var result2 = 5.IfElse(
|
||||
); // 6 (因为5不大于10,所以+1)
|
||||
```
|
||||
|
||||
### 15. As / Cast - 类型转换
|
||||
```csharp
|
||||
// 安全类型转换
|
||||
object obj = "Hello";
|
||||
var str = obj.As<string>(); // "Hello"
|
||||
var str2 = obj.Cast<string>(); // "Hello" (强制转换)
|
||||
```
|
||||
|
||||
### 16. Also / Let - 副作用和转换
|
||||
```csharp
|
||||
// 执行操作并返回原值
|
||||
var value = 42.Also(Console.WriteLine); // 输出42,返回42
|
||||
|
||||
// 转换值
|
||||
var result = 5.Let(x => x * 2); // 10
|
||||
```
|
||||
|
||||
### 17. TakeIf / TakeUnless - 条件取值
|
||||
- **TakeIf / TakeUnless** - 条件取值
|
||||
```csharp
|
||||
// 条件为真时返回值,否则返回null
|
||||
string str = "Hello";
|
||||
@ -150,20 +132,49 @@ var result3 = str.TakeUnless(s => s.Length > 10); // "Hello" (因为长度不大
|
||||
var result4 = str.TakeUnless(s => s.Length > 3); // null (因为长度大于3)
|
||||
```
|
||||
|
||||
### 18. Repeat - 重复执行
|
||||
### 4. Function Extensions - 函数式操作
|
||||
位于 `GFramework.Core.functional.functions` 命名空间,提供柯里化、偏函数应用等高级函数式特性。
|
||||
|
||||
#### 方法列表及用法:
|
||||
- **Curry** - 柯里化
|
||||
```csharp
|
||||
// 将多参数函数转换为链式单参数函数
|
||||
Func<int, int, int> add = (x, y) => x + y;
|
||||
var curriedAdd = add.Curry(); // 返回 Func<int, Func<int, int>>
|
||||
var addFive = curriedAdd(5); // 返回 Func<int, int>
|
||||
var result = addFive(3); // 8
|
||||
```
|
||||
|
||||
- **Uncurry** - 取消柯里化
|
||||
```csharp
|
||||
// 将柯里化函数转换回多参数函数
|
||||
var curriedAdd = ((Func<int, int, int>)((x, y) => x + y)).Curry();
|
||||
var uncurriedAdd = curriedAdd.Uncurry(); // 返回 Func<int, int, int>
|
||||
var result = uncurriedAdd(5, 3); // 8
|
||||
```
|
||||
|
||||
- **Partial** - 部分应用
|
||||
```csharp
|
||||
// 固定函数的部分参数
|
||||
Func<int, int, int> multiply = (x, y) => x * y;
|
||||
var double = multiply.Partial(2); // 固定第一个参数为2
|
||||
var result = double(5); // 10
|
||||
```
|
||||
|
||||
- **Repeat** - 重复执行
|
||||
```csharp
|
||||
// 重复执行函数n次
|
||||
var result = 2.Repeat(3, x => x * 2); // 2 -> 4 -> 8 -> 16
|
||||
```
|
||||
|
||||
### 19. Try - 安全执行
|
||||
- **Try** - 安全执行
|
||||
```csharp
|
||||
// 安全执行可能抛出异常的函数
|
||||
var (success, result, error) = 10.Try(x => 100 / x); // 成功,result为10
|
||||
var (success2, result2, error2) = 0.Try(x => 100 / x); // 失败,success2为false
|
||||
```
|
||||
|
||||
### 20. Memoize - 缓存结果
|
||||
- **Memoize** - 缓存结果
|
||||
```csharp
|
||||
// 缓存函数结果以提高性能
|
||||
Func<int, int> expensiveFunction = x =>
|
||||
@ -177,6 +188,25 @@ var result1 = memoized(5); // 首次调用需要1秒
|
||||
var result2 = memoized(5); // 立即返回,使用缓存结果
|
||||
```
|
||||
|
||||
### 5. Type Extensions - 类型转换
|
||||
位于 `GFramework.Core.functional.types` 命名空间,提供类型转换相关的扩展方法。
|
||||
|
||||
#### 方法列表及用法:
|
||||
- **As** - 安全类型转换
|
||||
```csharp
|
||||
// 安全类型转换,失败时返回null
|
||||
object obj = "Hello";
|
||||
var str = obj.As<string>(); // "Hello"
|
||||
var incompatible = obj.As<int>(); // null
|
||||
```
|
||||
|
||||
- **Cast** - 强制类型转换
|
||||
```csharp
|
||||
// 强制类型转换,失败时抛出异常
|
||||
object obj = "Hello";
|
||||
var str = obj.Cast<string>(); // "Hello"
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 链式操作
|
||||
Loading…
x
Reference in New Issue
Block a user