From 3493d6a4812da4cb24db6880ea5f5b5673b985f6 Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Sat, 31 Jan 2026 21:52:04 +0800 Subject: [PATCH] =?UTF-8?q?docs(functional):=20=E6=B7=BB=E5=8A=A0=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E5=BC=8F=E7=BC=96=E7=A8=8B=E7=B1=BB=E5=9E=8B=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E5=92=8C=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 Option 类型文档,包含核心类型及扩展方法说明 - 新增 Result 类型文档,包含核心类型及扩展方法说明 - 新增 Nullable Extensions 文档,提供可空类型转换功能说明 - 添加 Option 类型单元测试,覆盖基本功能和扩展方法 - 添加 Result 类型单元测试,验证成功失败结果处理 - 添加 Nullable Extensions 单元测试,确保类型转换正确性 - 添加 Option 和 Result 扩展方法的完整测试用例 - [release ci] --- .../types/NullableExtensionsTests.cs | 78 ++++++++ .../functional/types/OptionExtensionsTests.cs | 181 ++++++++++++++++++ .../functional/types/OptionTests.cs | 70 +++++++ .../types/OptionValueExtensionsTests.cs | 141 ++++++++++++++ .../functional/types/ResultExtensionsTests.cs | 171 +++++++++++++++++ .../functional/types/ResultTests.cs | 108 +++++++++++ GFramework.Core/functional/README.md | 176 +++++++++++++++++ 7 files changed, 925 insertions(+) create mode 100644 GFramework.Core.Tests/functional/types/NullableExtensionsTests.cs create mode 100644 GFramework.Core.Tests/functional/types/OptionExtensionsTests.cs create mode 100644 GFramework.Core.Tests/functional/types/OptionTests.cs create mode 100644 GFramework.Core.Tests/functional/types/OptionValueExtensionsTests.cs create mode 100644 GFramework.Core.Tests/functional/types/ResultExtensionsTests.cs create mode 100644 GFramework.Core.Tests/functional/types/ResultTests.cs diff --git a/GFramework.Core.Tests/functional/types/NullableExtensionsTests.cs b/GFramework.Core.Tests/functional/types/NullableExtensionsTests.cs new file mode 100644 index 0000000..a518fb2 --- /dev/null +++ b/GFramework.Core.Tests/functional/types/NullableExtensionsTests.cs @@ -0,0 +1,78 @@ +using GFramework.Core.functional.types; +using NUnit.Framework; + +namespace GFramework.Core.Tests.functional.types; + +/// +/// NullableExtensions扩展方法测试类,用于验证可空类型转换为Option类型的功能 +/// 包括引用类型和值类型的可空转换测试 +/// +[TestFixture] +public class NullableExtensionsTests +{ + /// + /// 测试引用类型可空转换 - 验证非null值转换为Some + /// + [Test] + public void NullableExtensions_ReferenceType_ToOption_Should_Create_Some_For_NonNull() + { + // Arrange + string? value = "Hello"; + + // Act + var option = value.ToOption(); + + // Assert + Assert.That(option.IsSome, Is.True); + Assert.That(option.Value, Is.EqualTo("Hello")); + } + + /// + /// 测试引用类型可空转换 - 验证null值转换为None + /// + [Test] + public void NullableExtensions_ReferenceType_ToOption_Should_Create_None_For_Null() + { + // Arrange + string? value = null; + + // Act + var option = value.ToOption(); + + // Assert + Assert.That(option.IsNone, Is.True); + } + + /// + /// 测试值类型可空转换 - 验证有值的可空值类型转换为Some + /// + [Test] + public void NullableExtensions_ValueType_ToOption_Should_Create_Some_For_HasValue() + { + // Arrange + int? value = 42; + + // Act + var option = value.ToOption(); + + // Assert + Assert.That(option.IsSome, Is.True); + Assert.That(option.Value, Is.EqualTo(42)); + } + + /// + /// 测试值类型可空转换 - 验证无值的可空值类型转换为None + /// + [Test] + public void NullableExtensions_ValueType_ToOption_Should_Create_None_For_NoValue() + { + // Arrange + int? value = null; + + // Act + var option = value.ToOption(); + + // Assert + Assert.That(option.IsNone, Is.True); + } +} \ No newline at end of file diff --git a/GFramework.Core.Tests/functional/types/OptionExtensionsTests.cs b/GFramework.Core.Tests/functional/types/OptionExtensionsTests.cs new file mode 100644 index 0000000..5f1dd2b --- /dev/null +++ b/GFramework.Core.Tests/functional/types/OptionExtensionsTests.cs @@ -0,0 +1,181 @@ +using GFramework.Core.functional.types; +using NUnit.Framework; + +namespace GFramework.Core.Tests.functional.types; + +/// +/// OptionExtensions扩展方法测试类,用于验证Option类型的功能扩展方法 +/// 包括映射、绑定、过滤和匹配操作等功能的测试 +/// +[TestFixture] +public class OptionExtensionsTests +{ + /// + /// 测试Map方法 - 验证Some值能正确映射 + /// + [Test] + public void Option_Map_Should_Transform_Some_Value() + { + // Arrange + var option = Option.Some("hello"); + + // Act + var result = option.Map(s => s.Length); + + // Assert + Assert.That(result.IsSome, Is.True); + Assert.That(result.Value, Is.EqualTo(5)); + } + + /// + /// 测试Map方法 - 验证None映射后仍为None + /// + [Test] + public void Option_Map_Should_Return_None_For_None() + { + // Arrange + var option = Option.None(); + + // Act + var result = option.Map(s => s.Length); + + // Assert + Assert.That(result.IsNone, Is.True); + } + + /// + /// 测试Bind方法 - 验证Some值能正确绑定到另一个Option + /// + [Test] + public void Option_Bind_Should_Transform_Some_To_Another_Option() + { + // Arrange + var option = Option.Some("hello"); + + // Act + var result = option.Bind(s => s.Length > 3 ? Option.Some(s.Length) : Option.None()); + + // Assert + Assert.That(result.IsSome, Is.True); + Assert.That(result.Value, Is.EqualTo(5)); + } + + /// + /// 测试Bind方法 - 验证None绑定后仍为None + /// + [Test] + public void Option_Bind_Should_Return_None_For_None() + { + // Arrange + var option = Option.None(); + + // Act + var result = option.Bind(s => Option.Some(s.Length)); + + // Assert + Assert.That(result.IsNone, Is.True); + } + + /// + /// 测试Bind方法 - 验证Some值绑定到None的情况 + /// + [Test] + public void Option_Bind_Should_Return_None_When_Binder_Returns_None() + { + // Arrange + var option = Option.Some("hi"); // 长度小于3 + + // Act + var result = option.Bind(s => s.Length > 3 ? Option.Some(s.Length) : Option.None()); + + // Assert + Assert.That(result.IsNone, Is.True); + } + + /// + /// 测试Filter方法 - 验证满足条件的Some值保留 + /// + [Test] + public void Option_Filter_Should_Keep_Some_When_Predicate_Matches() + { + // Arrange + var option = Option.Some("hello"); + + // Act + var result = option.Filter(s => s.Length > 3); + + // Assert + Assert.That(result.IsSome, Is.True); + Assert.That(result.Value, Is.EqualTo("hello")); + } + + /// + /// 测试Filter方法 - 验证不满足条件的Some值变为None + /// + [Test] + public void Option_Filter_Should_Return_None_When_Predicate_Does_Not_Match() + { + // Arrange + var option = Option.Some("hi"); + + // Act + var result = option.Filter(s => s.Length > 3); + + // Assert + Assert.That(result.IsNone, Is.True); + } + + /// + /// 测试Filter方法 - 验证None过滤后仍为None + /// + [Test] + public void Option_Filter_Should_Return_None_For_None() + { + // Arrange + var option = Option.None(); + + // Act + var result = option.Filter(s => s.Length > 3); + + // Assert + Assert.That(result.IsNone, Is.True); + } + + /// + /// 测试Match方法 - 验证Some值执行some分支 + /// + [Test] + public void Option_Match_Should_Execute_Some_Branch_For_Some() + { + // Arrange + var option = Option.Some("hello"); + + // Act + var result = option.Match( + some: s => $"Value: {s}", + none: () => "No value" + ); + + // Assert + Assert.That(result, Is.EqualTo("Value: hello")); + } + + /// + /// 测试Match方法 - 验证None值执行none分支 + /// + [Test] + public void Option_Match_Should_Execute_None_Branch_For_None() + { + // Arrange + var option = Option.None(); + + // Act + var result = option.Match( + some: s => $"Value: {s}", + none: () => "No value" + ); + + // Assert + Assert.That(result, Is.EqualTo("No value")); + } +} \ No newline at end of file diff --git a/GFramework.Core.Tests/functional/types/OptionTests.cs b/GFramework.Core.Tests/functional/types/OptionTests.cs new file mode 100644 index 0000000..bbb59ba --- /dev/null +++ b/GFramework.Core.Tests/functional/types/OptionTests.cs @@ -0,0 +1,70 @@ +using GFramework.Core.functional.types; +using NUnit.Framework; + +namespace GFramework.Core.Tests.functional.types; + +/// +/// Option类型测试类,用于验证Option类型的基本功能 +/// 包括创建Some和None实例、值访问等功能的测试 +/// +[TestFixture] +public class OptionTests +{ + /// + /// 测试创建Some实例 - 验证非null值能正确创建Some + /// + [Test] + public void Option_Some_Should_Create_WithValue() + { + // Arrange + var value = "Hello"; + + // Act + var option = Option.Some(value); + + // Assert + Assert.That(option.IsSome, Is.True); + Assert.That(option.IsNone, Is.False); + Assert.That(option.Value, Is.EqualTo(value)); + } + + /// + /// 测试创建Some实例 - 验证null值时抛出异常 + /// + [Test] + public void Option_Some_Should_Throw_When_Value_Is_Null() + { + // Act & Assert + Assert.Throws(() => Option.Some(null!)); + } + + /// + /// 测试创建None实例 - 验证能正确创建None + /// + [Test] + public void Option_None_Should_Create_Empty_Instance() + { + // Act + var option = Option.None(); + + // Assert + Assert.That(option.IsNone, Is.True); + Assert.That(option.IsSome, Is.False); + } + + /// + /// 测试访问None的值 - 验证抛出异常 + /// + [Test] + public void Option_None_Value_Access_Should_Throw_Exception() + { + // Arrange + var option = Option.None(); + + // Act & Assert + Assert.Throws(() => + { + var _ = option.Value; + }); + } +} \ No newline at end of file diff --git a/GFramework.Core.Tests/functional/types/OptionValueExtensionsTests.cs b/GFramework.Core.Tests/functional/types/OptionValueExtensionsTests.cs new file mode 100644 index 0000000..653a64e --- /dev/null +++ b/GFramework.Core.Tests/functional/types/OptionValueExtensionsTests.cs @@ -0,0 +1,141 @@ +using GFramework.Core.functional.types; +using NUnit.Framework; + +namespace GFramework.Core.Tests.functional.types; + +/// +/// OptionValueExtensions扩展方法测试类,用于验证Option类型值的操作扩展方法 +/// 包括获取默认值、备选Option等功能的测试 +/// +[TestFixture] +public class OptionValueExtensionsTests +{ + /// + /// 测试GetOrElse方法 - 验证Some值直接返回其值 + /// + [Test] + public void OptionValueExtensions_GetOrElse_Should_Return_Value_For_Some() + { + // Arrange + var option = Option.Some("actual value"); + + // Act + var result = option.GetOrElse("default value"); + + // Assert + Assert.That(result, Is.EqualTo("actual value")); + } + + /// + /// 测试GetOrElse方法 - 验证None值返回默认值 + /// + [Test] + public void OptionValueExtensions_GetOrElse_Should_Return_Default_For_None() + { + // Arrange + var option = Option.None(); + + // Act + var result = option.GetOrElse("default value"); + + // Assert + Assert.That(result, Is.EqualTo("default value")); + } + + /// + /// 测试GetOrElse方法(工厂函数) - 验证Some值直接返回其值(不调用工厂) + /// + [Test] + public void OptionValueExtensions_GetOrElse_With_Factory_Should_Return_Value_For_Some() + { + // Arrange + var option = Option.Some("actual value"); + var factoryCalled = false; + + // Act + var result = option.GetOrElse(() => + { + factoryCalled = true; + return "factory value"; + }); + + // Assert + Assert.That(result, Is.EqualTo("actual value")); + Assert.That(factoryCalled, Is.False); + } + + /// + /// 测试GetOrElse方法(工厂函数) - 验证None值调用工厂函数 + /// + [Test] + public void OptionValueExtensions_GetOrElse_With_Factory_Should_Call_Factory_For_None() + { + // Arrange + var option = Option.None(); + var factoryCalled = false; + + // Act + var result = option.GetOrElse(() => + { + factoryCalled = true; + return "factory value"; + }); + + // Assert + Assert.That(result, Is.EqualTo("factory value")); + Assert.That(factoryCalled, Is.True); + } + + /// + /// 测试OrElse方法 - 验证Some值返回自身 + /// + [Test] + public void OptionValueExtensions_OrElse_Should_Return_Self_For_Some() + { + // Arrange + var option = Option.Some("primary value"); + var fallback = Option.Some("fallback value"); + + // Act + var result = option.OrElse(fallback); + + // Assert + Assert.That(result.IsSome, Is.True); + Assert.That(result.Value, Is.EqualTo("primary value")); + } + + /// + /// 测试OrElse方法 - 验证None值返回备选Option + /// + [Test] + public void OptionValueExtensions_OrElse_Should_Return_Fallback_For_None() + { + // Arrange + var option = Option.None(); + var fallback = Option.Some("fallback value"); + + // Act + var result = option.OrElse(fallback); + + // Assert + Assert.That(result.IsSome, Is.True); + Assert.That(result.Value, Is.EqualTo("fallback value")); + } + + /// + /// 测试OrElse方法 - 验证None值返回备选None + /// + [Test] + public void OptionValueExtensions_OrElse_Should_Return_Fallback_None_For_None() + { + // Arrange + var option = Option.None(); + var fallback = Option.None(); + + // Act + var result = option.OrElse(fallback); + + // Assert + Assert.That(result.IsNone, Is.True); + } +} \ No newline at end of file diff --git a/GFramework.Core.Tests/functional/types/ResultExtensionsTests.cs b/GFramework.Core.Tests/functional/types/ResultExtensionsTests.cs new file mode 100644 index 0000000..4c867b6 --- /dev/null +++ b/GFramework.Core.Tests/functional/types/ResultExtensionsTests.cs @@ -0,0 +1,171 @@ +using GFramework.Core.functional.types; +using NUnit.Framework; + +namespace GFramework.Core.Tests.functional.types; + +/// +/// ResultExtensions扩展方法测试类,用于验证Result类型的功能扩展方法 +/// 包括映射、绑定、错误映射和匹配操作等功能的测试 +/// +[TestFixture] +public class ResultExtensionsTests +{ + /// + /// 测试Map方法 - 验证Success值能正确映射 + /// + [Test] + public void Result_Map_Should_Transform_Success_Value() + { + // Arrange + var result = Result.Success("hello"); + + // Act + var mappedResult = result.Map(s => s.Length); + + // Assert + Assert.That(mappedResult.IsSuccess, Is.True); + Assert.That(mappedResult.SuccessValue, Is.EqualTo(5)); + } + + /// + /// 测试Map方法 - 验证Failure映射后仍保持Failure状态 + /// + [Test] + public void Result_Map_Should_Keep_Failure_For_Failure() + { + // Arrange + var result = Result.Failure("error occurred"); + + // Act + var mappedResult = result.Map(s => s.Length); + + // Assert + Assert.That(mappedResult.IsFailure, Is.True); + Assert.That(mappedResult.ErrorValue, Is.EqualTo("error occurred")); + } + + /// + /// 测试Bind方法 - 验证Success值能正确绑定到另一个Result + /// + [Test] + public void Result_Bind_Should_Transform_Success_To_Another_Result() + { + // Arrange + var result = Result.Success("hello"); + + // Act + var boundResult = result.Bind(s => + s.Length > 3 ? Result.Success(s.Length) : Result.Failure("Length too small")); + + // Assert + Assert.That(boundResult.IsSuccess, Is.True); + Assert.That(boundResult.SuccessValue, Is.EqualTo(5)); + } + + /// + /// 测试Bind方法 - 验证Failure绑定后仍保持Failure状态 + /// + [Test] + public void Result_Bind_Should_Keep_Failure_For_Failure() + { + // Arrange + var result = Result.Failure("initial error"); + + // Act + var boundResult = result.Bind(s => Result.Success(s.Length)); + + // Assert + Assert.That(boundResult.IsFailure, Is.True); + Assert.That(boundResult.ErrorValue, Is.EqualTo("initial error")); + } + + /// + /// 测试Bind方法 - 验证Success值绑定到Failure的情况 + /// + [Test] + public void Result_Bind_Should_Allow_Transition_To_Failure() + { + // Arrange + var result = Result.Success("hi"); // 长度小于3 + + // Act + var boundResult = result.Bind(s => + s.Length > 3 ? Result.Success(s.Length) : Result.Failure("Length too small")); + + // Assert + Assert.That(boundResult.IsFailure, Is.True); + Assert.That(boundResult.ErrorValue, Is.EqualTo("Length too small")); + } + + /// + /// 测试MapError方法 - 验证Failure错误值能正确映射 + /// + [Test] + public void Result_MapError_Should_Transform_Failure_Error() + { + // Arrange + var result = Result.Failure("original error"); + + // Act + var mappedErrorResult = result.MapError(err => $"Mapped: {err}"); + + // Assert + Assert.That(mappedErrorResult.IsFailure, Is.True); + Assert.That(mappedErrorResult.ErrorValue, Is.EqualTo("Mapped: original error")); + } + + /// + /// 测试MapError方法 - 验证Success映射错误后仍保持Success状态 + /// + [Test] + public void Result_MapError_Should_Keep_Success_For_Success() + { + // Arrange + var result = Result.Success("success data"); + + // Act + var mappedErrorResult = result.MapError(err => $"Mapped: {err}"); + + // Assert + Assert.That(mappedErrorResult.IsSuccess, Is.True); + Assert.That(mappedErrorResult.SuccessValue, Is.EqualTo("success data")); + } + + /// + /// 测试Match方法 - 验证Success值执行onSuccess分支 + /// + [Test] + public void Result_Match_Should_Execute_OnSuccess_Branch_For_Success() + { + // Arrange + var result = Result.Success("success data"); + + // Act + var matchedResult = result.Match( + onSuccess: data => $"Success: {data}", + onFailure: error => $"Error: {error}" + ); + + // Assert + Assert.That(matchedResult, Is.EqualTo("Success: success data")); + } + + /// + /// 测试Match方法 - 验证Failure值执行onFailure分支 + /// + [Test] + public void Result_Match_Should_Execute_OnFailure_Branch_For_Failure() + { + // Arrange + var result = Result.Failure("something failed"); + + // Act + var matchedResult = result.Match( + onSuccess: data => $"Success: {data}", + onFailure: error => $"Error: {error}" + ); + + // Assert + Assert.That(matchedResult, Is.EqualTo("Error: something failed")); + } +} \ No newline at end of file diff --git a/GFramework.Core.Tests/functional/types/ResultTests.cs b/GFramework.Core.Tests/functional/types/ResultTests.cs new file mode 100644 index 0000000..0ee9947 --- /dev/null +++ b/GFramework.Core.Tests/functional/types/ResultTests.cs @@ -0,0 +1,108 @@ +using GFramework.Core.functional.types; +using NUnit.Framework; + +namespace GFramework.Core.Tests.functional.types; + +/// +/// Result类型测试类,用于验证Result类型的基本功能 +/// 包括创建Success和Failure实例、值访问等功能的测试 +/// +[TestFixture] +public class ResultTests +{ + /// + /// 测试创建Success实例 - 验证能正确创建成功结果 + /// + [Test] + public void Result_Success_Should_Create_With_Value() + { + // Arrange + var value = "Success data"; + + // Act + var result = Result.Success(value); + + // Assert + Assert.That(result.IsSuccess, Is.True); + Assert.That(result.IsFailure, Is.False); + Assert.That(result.SuccessValue, Is.EqualTo(value)); + } + + /// + /// 测试访问Success值 - 验证能正确获取成功值 + /// + [Test] + public void Result_Success_Value_Access_Should_Work() + { + // Arrange + var result = Result.Success("test"); + + // Act & Assert + Assert.That(result.IsSuccess, Is.True); + Assert.That(result.SuccessValue, Is.EqualTo("test")); + } + + /// + /// 测试访问Success的错误值 - 验证在成功状态下访问错误值抛出异常 + /// + [Test] + public void Result_Success_Error_Access_Should_Throw_Exception() + { + // Arrange + var result = Result.Success("success"); + + // Act & Assert + Assert.Throws(() => + { + var _ = result.ErrorValue; + }); + } + + /// + /// 测试创建Failure实例 - 验证能正确创建失败结果 + /// + [Test] + public void Result_Failure_Should_Create_With_Error() + { + // Arrange + var error = "Something went wrong"; + + // Act + var result = Result.Failure(error); + + // Assert + Assert.That(result.IsFailure, Is.True); + Assert.That(result.IsSuccess, Is.False); + Assert.That(result.ErrorValue, Is.EqualTo(error)); + } + + /// + /// 测试访问Failure值 - 验证能正确获取错误值 + /// + [Test] + public void Result_Failure_Value_Access_Should_Work() + { + // Arrange + var result = Result.Failure("error"); + + // Act & Assert + Assert.That(result.IsFailure, Is.True); + Assert.That(result.ErrorValue, Is.EqualTo("error")); + } + + /// + /// 测试访问Failure的成功值 - 验证在失败状态下访问成功值抛出异常 + /// + [Test] + public void Result_Failure_Success_Access_Should_Throw_Exception() + { + // Arrange + var result = Result.Failure("error"); + + // Act & Assert + Assert.Throws(() => + { + var _ = result.SuccessValue; + }); + } +} \ No newline at end of file diff --git a/GFramework.Core/functional/README.md b/GFramework.Core/functional/README.md index bd7982b..4febcc2 100644 --- a/GFramework.Core/functional/README.md +++ b/GFramework.Core/functional/README.md @@ -207,6 +207,182 @@ object obj = "Hello"; var str = obj.Cast(); // "Hello" ``` +### 6. Option Type - 可选值类型 + +位于 `GFramework.Core.functional.types` 命名空间,提供表示可能存在或不存在的值的类型。 + +#### 核心类型及用法: + +- **Option<T>** - 表示可能包含值或不包含值的类型 + +```csharp +// 创建包含值的Option +var someValue = Option<string>.Some("Hello"); +Console.WriteLine(someValue.IsSome); // True +Console.WriteLine(someValue.Value); // "Hello" + +// 创建空的Option +var noValue = Option<string>.None(); +Console.WriteLine(noValue.IsNone); // True +``` + +#### Option扩展方法: + +- **Map** - 对Option中的值进行映射转换 + +```csharp +var someValue = Option<string>.Some("hello"); +var lengthOption = someValue.Map(s => s.Length); // Some(5) + +var noneValue = Option<string>.None(); +var noneLength = noneValue.Map(s => s.Length); // None +``` + +- **Bind** - 将Option中的值转换为另一个Option + +```csharp +var someValue = Option<string>.Some("hello"); +var result = someValue.Bind(s => s.Length > 3 ? Option<int>.Some(s.Length) : Option<int>.None()); // Some(5) + +var shortValue = Option<string>.Some("hi"); +var result2 = shortValue.Bind(s => s.Length > 3 ? Option<int>.Some(s.Length) : Option<int>.None()); // None +``` + +- **Filter** - 根据条件过滤Option中的值 + +```csharp +var someValue = Option<string>.Some("hello"); +var filtered = someValue.Filter(s => s.Length > 3); // Some("hello") +var filtered2 = someValue.Filter(s => s.Length > 10); // None +``` + +- **Match** - 模式匹配Option的状态 + +```csharp +var someValue = Option<string>.Some("hello"); +var result = someValue.Match( + some: s => $"Value: {s}", + none: () => "No value" +); // "Value: hello" + +var noneValue = Option<string>.None(); +var result2 = noneValue.Match( + some: s => $"Value: {s}", + none: () => "No value" +); // "No value" +``` + +- **GetOrElse** - 获取值或返回默认值 + +```csharp +var someValue = Option<string>.Some("hello"); +var value1 = someValue.GetOrElse("default"); // "hello" + +var noneValue = Option<string>.None(); +var value2 = noneValue.GetOrElse("default"); // "default" +``` + +- **OrElse** - 当前Option为空时返回备选Option + +```csharp +var someValue = Option<string>.Some("primary"); +var result1 = someValue.OrElse(Option<string>.Some("fallback")); // Some("primary") + +var noneValue = Option<string>.None(); +var result2 = noneValue.OrElse(Option<string>.Some("fallback")); // Some("fallback") +``` + +### 7. Result Type - 结果类型 + +位于 `GFramework.Core.functional.types` 命名空间,提供表示成功或失败结果的类型。 + +#### 核心类型及用法: + +- **Result<TSuccess, TError>** - 表示可能成功或失败的计算结果 + +```csharp +// 创建成功的结果 +var successResult = Result<string, string>.Success("Operation successful"); +Console.WriteLine(successResult.IsSuccess); // True +Console.WriteLine(successResult.SuccessValue); // "Operation successful" + +// 创建失败的结果 +var failureResult = Result<string, string>.Failure("Operation failed"); +Console.WriteLine(failureResult.IsFailure); // True +Console.WriteLine(failureResult.ErrorValue); // "Operation failed" +``` + +#### Result扩展方法: + +- **Map** - 对成功值进行映射转换 + +```csharp +var successResult = Result<string, string>.Success("hello"); +var lengthResult = successResult.Map(s => s.Length); // Success(5) + +var failureResult = Result<string, string>.Failure("error"); +var lengthResult2 = failureResult.Map(s => s.Length); // Failure("error") +``` + +- **Bind** - 将成功值转换为另一个Result + +```csharp +var successResult = Result<string, string>.Success("hello"); +var result = successResult.Bind(s => + s.Length > 3 ? + Result<int, string>.Success(s.Length) : + Result<int, string>.Failure("Length too small")); +// Result<int, string>.Success(5) +``` + +- **MapError** - 对错误值进行映射转换 + +```csharp +var failureResult = Result<string, string>.Failure("original error"); +var mappedErrorResult = failureResult.MapError(err => $"Mapped: {err}"); +// Result<string, string>.Failure("Mapped: original error") +``` + +- **Match** - 模式匹配Result的状态 + +```csharp +var successResult = Result<string, string>.Success("data"); +var result = successResult.Match( + onSuccess: data => $"Success: {data}", + onFailure: error => $"Error: {error}" +); // "Success: data" + +var failureResult = Result<string, string>.Failure("error"); +var result2 = failureResult.Match( + onSuccess: data => $"Success: {data}", + onFailure: error => $"Error: {error}" +); // "Error: error" +``` + +### 8. Nullable Extensions - 可空类型扩展 + +位于 `GFramework.Core.functional.types` 命名空间,提供将可空类型转换为Option类型的方法。 + +#### 方法列表及用法: + +- **ToOption** - 将可空类型转换为Option + +```csharp +// 引用类型可空转换 +string? stringValue = "Hello"; +var someOption = stringValue.ToOption(); // Some("Hello") + +string? nullString = null; +var noneOption = nullString.ToOption(); // None + +// 值类型可空转换 +int? intValue = 42; +var someIntOption = intValue.ToOption(); // Some(42) + +int? nullInt = null; +var noneIntOption = nullInt.ToOption(); // None +``` + ## 使用示例 ### 链式操作