diff --git a/src/Cortex.Tests/Cortex.Tests.csproj b/src/Cortex.Tests/Cortex.Tests.csproj
index 7194f92..8ee5bc3 100644
--- a/src/Cortex.Tests/Cortex.Tests.csproj
+++ b/src/Cortex.Tests/Cortex.Tests.csproj
@@ -31,6 +31,7 @@
+
diff --git a/src/Cortex.Tests/Types/Tests/AnyOfTests.cs b/src/Cortex.Tests/Types/Tests/AnyOfTests.cs
new file mode 100644
index 0000000..45833b5
--- /dev/null
+++ b/src/Cortex.Tests/Types/Tests/AnyOfTests.cs
@@ -0,0 +1,649 @@
+using Cortex.Types;
+
+namespace Cortex.Tests.Types.Tests
+{
+ public class AnyOfTests
+ {
+ #region AnyOf Tests
+
+ [Fact]
+ public void AnyOf2_ImplicitConversion_FromT1_SetsCorrectTypeIndex()
+ {
+ AnyOf value = 42;
+
+ Assert.Contains(0, value.TypeIndices);
+ Assert.Equal(42, value.Value);
+ }
+
+ [Fact]
+ public void AnyOf2_ImplicitConversion_FromT2_SetsCorrectTypeIndex()
+ {
+ AnyOf value = "hello";
+
+ Assert.Contains(1, value.TypeIndices);
+ Assert.Equal("hello", value.Value);
+ }
+
+ [Fact]
+ public void AnyOf2_Is_ReturnsTrue_WhenTypeMatches()
+ {
+ AnyOf value = 42;
+
+ Assert.True(value.Is());
+ Assert.False(value.Is());
+ }
+
+ [Fact]
+ public void AnyOf2_As_ReturnsValue_WhenTypeMatches()
+ {
+ AnyOf value = 42;
+
+ Assert.Equal(42, value.As());
+ }
+
+ [Fact]
+ public void AnyOf2_As_ThrowsInvalidCastException_WhenTypeMismatch()
+ {
+ AnyOf value = 42;
+
+ Assert.Throws(() => value.As());
+ }
+
+ [Fact]
+ public void AnyOf2_TryGet_ReturnsTrue_WhenTypeMatches()
+ {
+ AnyOf value = 42;
+
+ Assert.True(value.TryGet(out int result));
+ Assert.Equal(42, result);
+ }
+
+ [Fact]
+ public void AnyOf2_TryGet_ReturnsFalse_WhenTypeMismatch()
+ {
+ AnyOf value = 42;
+
+ Assert.False(value.TryGet(out string? result));
+ }
+
+ [Fact]
+ public void AnyOf2_Match_ExecutesCorrectHandler()
+ {
+ AnyOf intValue = 42;
+ AnyOf stringValue = "hello";
+
+ var intResult = intValue.Match(
+ i => $"int: {i}",
+ s => $"string: {s}");
+
+ var stringResult = stringValue.Match(
+ i => $"int: {i}",
+ s => $"string: {s}");
+
+ Assert.Equal("int: 42", intResult);
+ Assert.Equal("string: hello", stringResult);
+ }
+
+ [Fact]
+ public void AnyOf2_Switch_ExecutesCorrectAction()
+ {
+ AnyOf value = 42;
+ int? capturedInt = null;
+ string? capturedString = null;
+
+ value.Switch(
+ i => capturedInt = i,
+ s => capturedString = s);
+
+ Assert.Equal(42, capturedInt);
+ Assert.Null(capturedString);
+ }
+
+ [Fact]
+ public void AnyOf2_GetMatchingTypes_ReturnsMatchingTypes()
+ {
+ AnyOf value = 42;
+
+ var matchingTypes = value.GetMatchingTypes().ToList();
+
+ Assert.Single(matchingTypes);
+ Assert.Contains(typeof(int), matchingTypes);
+ }
+
+ [Fact]
+ public void AnyOf2_Equals_ReturnsTrue_ForSameValues()
+ {
+ AnyOf value1 = 42;
+ AnyOf value2 = 42;
+
+ Assert.Equal(value1, value2);
+ Assert.True(value1 == value2);
+ Assert.False(value1 != value2);
+ }
+
+ [Fact]
+ public void AnyOf2_ToString_ReturnsValueString()
+ {
+ AnyOf value = 42;
+
+ Assert.Equal("42", value.ToString());
+ }
+
+ #endregion
+
+ #region AnyOf Tests
+
+ [Fact]
+ public void AnyOf3_ImplicitConversion_FromEachType_SetsCorrectTypeIndex()
+ {
+ AnyOf intVal = 42;
+ AnyOf strVal = "hello";
+ AnyOf dblVal = 3.14;
+
+ Assert.Contains(0, intVal.TypeIndices);
+ Assert.Contains(1, strVal.TypeIndices);
+ Assert.Contains(2, dblVal.TypeIndices);
+ }
+
+ [Fact]
+ public void AnyOf3_Match_ExecutesCorrectHandler()
+ {
+ AnyOf value = 3.14;
+
+ var result = value.Match(
+ i => "int",
+ s => "string",
+ d => "double");
+
+ Assert.Equal("double", result);
+ }
+
+ [Fact]
+ public void AnyOf3_Switch_ExecutesCorrectAction()
+ {
+ AnyOf value = "hello";
+ string? captured = null;
+
+ value.Switch(
+ i => { },
+ s => captured = s,
+ d => { });
+
+ Assert.Equal("hello", captured);
+ }
+
+ [Fact]
+ public void AnyOf3_GetMatchingTypes_ReturnsMatchingTypes()
+ {
+ AnyOf value = 3.14;
+
+ var matchingTypes = value.GetMatchingTypes().ToList();
+
+ Assert.Single(matchingTypes);
+ Assert.Contains(typeof(double), matchingTypes);
+ }
+
+ #endregion
+
+ #region AnyOf Tests
+
+ [Fact]
+ public void AnyOf4_ImplicitConversion_FromEachType_SetsCorrectTypeIndex()
+ {
+ AnyOf val1 = 42;
+ AnyOf val2 = "hello";
+ AnyOf val3 = 3.14;
+ AnyOf val4 = true;
+
+ Assert.Contains(0, val1.TypeIndices);
+ Assert.Contains(1, val2.TypeIndices);
+ Assert.Contains(2, val3.TypeIndices);
+ Assert.Contains(3, val4.TypeIndices);
+ }
+
+ [Fact]
+ public void AnyOf4_Match_ExecutesCorrectHandler()
+ {
+ AnyOf value = true;
+
+ var result = value.Match(
+ i => "int",
+ s => "string",
+ d => "double",
+ b => "bool");
+
+ Assert.Equal("bool", result);
+ }
+
+ [Fact]
+ public void AnyOf4_GetMatchingTypes_ReturnsMatchingTypes()
+ {
+ AnyOf value = true;
+
+ var matchingTypes = value.GetMatchingTypes().ToList();
+
+ Assert.Single(matchingTypes);
+ Assert.Contains(typeof(bool), matchingTypes);
+ }
+
+ #endregion
+
+ #region AnyOf Tests
+
+ [Fact]
+ public void AnyOf5_ImplicitConversion_FromEachType_SetsCorrectTypeIndex()
+ {
+ AnyOf val1 = 42;
+ AnyOf val2 = "hello";
+ AnyOf val3 = 3.14;
+ AnyOf val4 = true;
+ AnyOf val5 = 'x';
+
+ Assert.Contains(0, val1.TypeIndices);
+ Assert.Contains(1, val2.TypeIndices);
+ Assert.Contains(2, val3.TypeIndices);
+ Assert.Contains(3, val4.TypeIndices);
+ Assert.Contains(4, val5.TypeIndices);
+ }
+
+ [Fact]
+ public void AnyOf5_Match_ExecutesCorrectHandler()
+ {
+ AnyOf value = 'x';
+
+ var result = value.Match(
+ i => "int",
+ s => "string",
+ d => "double",
+ b => "bool",
+ c => "char");
+
+ Assert.Equal("char", result);
+ }
+
+ [Fact]
+ public void AnyOf5_Switch_ExecutesCorrectAction()
+ {
+ AnyOf value = 'x';
+ char? captured = null;
+
+ value.Switch(
+ i => { },
+ s => { },
+ d => { },
+ b => { },
+ c => captured = c);
+
+ Assert.Equal('x', captured);
+ }
+
+ [Fact]
+ public void AnyOf5_TryGet_WorksCorrectly()
+ {
+ AnyOf value = 3.14;
+
+ Assert.True(value.TryGet(out double d));
+ Assert.Equal(3.14, d);
+ Assert.False(value.TryGet(out int _));
+ }
+
+ [Fact]
+ public void AnyOf5_GetMatchingTypes_ReturnsMatchingTypes()
+ {
+ AnyOf value = 'x';
+
+ var matchingTypes = value.GetMatchingTypes().ToList();
+
+ Assert.Single(matchingTypes);
+ Assert.Contains(typeof(char), matchingTypes);
+ }
+
+ [Fact]
+ public void AnyOf5_Equals_WorksCorrectly()
+ {
+ AnyOf val1 = 'x';
+ AnyOf val2 = 'x';
+ AnyOf val3 = 'y';
+
+ Assert.Equal(val1, val2);
+ Assert.NotEqual(val1, val3);
+ }
+
+ #endregion
+
+ #region AnyOf Tests
+
+ [Fact]
+ public void AnyOf6_ImplicitConversion_FromEachType_SetsCorrectTypeIndex()
+ {
+ AnyOf val1 = 42;
+ AnyOf val2 = "hello";
+ AnyOf val3 = 3.14;
+ AnyOf val4 = true;
+ AnyOf val5 = 'x';
+ AnyOf val6 = 100L;
+
+ Assert.Contains(0, val1.TypeIndices);
+ Assert.Contains(1, val2.TypeIndices);
+ Assert.Contains(2, val3.TypeIndices);
+ Assert.Contains(3, val4.TypeIndices);
+ Assert.Contains(4, val5.TypeIndices);
+ Assert.Contains(5, val6.TypeIndices);
+ }
+
+ [Fact]
+ public void AnyOf6_Match_ExecutesCorrectHandler()
+ {
+ AnyOf value = 100L;
+
+ var result = value.Match(
+ i => "int",
+ s => "string",
+ d => "double",
+ b => "bool",
+ c => "char",
+ l => "long");
+
+ Assert.Equal("long", result);
+ }
+
+ [Fact]
+ public void AnyOf6_Switch_ExecutesCorrectAction()
+ {
+ AnyOf value = 100L;
+ long? captured = null;
+
+ value.Switch(
+ i => { },
+ s => { },
+ d => { },
+ b => { },
+ c => { },
+ l => captured = l);
+
+ Assert.Equal(100L, captured);
+ }
+
+ [Fact]
+ public void AnyOf6_GetMatchingTypes_ReturnsMatchingTypes()
+ {
+ AnyOf value = 100L;
+
+ var matchingTypes = value.GetMatchingTypes().ToList();
+
+ Assert.Single(matchingTypes);
+ Assert.Contains(typeof(long), matchingTypes);
+ }
+
+ #endregion
+
+ #region AnyOf Tests
+
+ [Fact]
+ public void AnyOf7_ImplicitConversion_FromEachType_SetsCorrectTypeIndex()
+ {
+ AnyOf val1 = 42;
+ AnyOf val2 = "hello";
+ AnyOf val3 = 3.14;
+ AnyOf val4 = true;
+ AnyOf val5 = 'x';
+ AnyOf val6 = 100L;
+ AnyOf val7 = 1.5f;
+
+ Assert.Contains(0, val1.TypeIndices);
+ Assert.Contains(1, val2.TypeIndices);
+ Assert.Contains(2, val3.TypeIndices);
+ Assert.Contains(3, val4.TypeIndices);
+ Assert.Contains(4, val5.TypeIndices);
+ Assert.Contains(5, val6.TypeIndices);
+ Assert.Contains(6, val7.TypeIndices);
+ }
+
+ [Fact]
+ public void AnyOf7_Match_ExecutesCorrectHandler()
+ {
+ AnyOf value = 1.5f;
+
+ var result = value.Match(
+ i => "int",
+ s => "string",
+ d => "double",
+ b => "bool",
+ c => "char",
+ l => "long",
+ f => "float");
+
+ Assert.Equal("float", result);
+ }
+
+ [Fact]
+ public void AnyOf7_Switch_ExecutesCorrectAction()
+ {
+ AnyOf value = 1.5f;
+ float? captured = null;
+
+ value.Switch(
+ i => { },
+ s => { },
+ d => { },
+ b => { },
+ c => { },
+ l => { },
+ f => captured = f);
+
+ Assert.Equal(1.5f, captured);
+ }
+
+ [Fact]
+ public void AnyOf7_GetMatchingTypes_ReturnsMatchingTypes()
+ {
+ AnyOf value = 1.5f;
+
+ var matchingTypes = value.GetMatchingTypes().ToList();
+
+ Assert.Single(matchingTypes);
+ Assert.Contains(typeof(float), matchingTypes);
+ }
+
+ [Fact]
+ public void AnyOf7_Equality_WorksCorrectly()
+ {
+ AnyOf val1 = 1.5f;
+ AnyOf val2 = 1.5f;
+
+ Assert.True(val1 == val2);
+ Assert.False(val1 != val2);
+ }
+
+ #endregion
+
+ #region AnyOf Tests
+
+ [Fact]
+ public void AnyOf8_ImplicitConversion_FromEachType_SetsCorrectTypeIndex()
+ {
+ AnyOf val1 = 42;
+ AnyOf val2 = "hello";
+ AnyOf val3 = 3.14;
+ AnyOf val4 = true;
+ AnyOf val5 = 'x';
+ AnyOf val6 = 100L;
+ AnyOf val7 = 1.5f;
+ AnyOf val8 = 99.99m;
+
+ Assert.Contains(0, val1.TypeIndices);
+ Assert.Contains(1, val2.TypeIndices);
+ Assert.Contains(2, val3.TypeIndices);
+ Assert.Contains(3, val4.TypeIndices);
+ Assert.Contains(4, val5.TypeIndices);
+ Assert.Contains(5, val6.TypeIndices);
+ Assert.Contains(6, val7.TypeIndices);
+ Assert.Contains(7, val8.TypeIndices);
+ }
+
+ [Fact]
+ public void AnyOf8_Match_ExecutesCorrectHandler()
+ {
+ AnyOf value = 99.99m;
+
+ var result = value.Match(
+ i => "int",
+ s => "string",
+ d => "double",
+ b => "bool",
+ c => "char",
+ l => "long",
+ f => "float",
+ m => "decimal");
+
+ Assert.Equal("decimal", result);
+ }
+
+ [Fact]
+ public void AnyOf8_Switch_ExecutesCorrectAction()
+ {
+ AnyOf value = 99.99m;
+ decimal? captured = null;
+
+ value.Switch(
+ i => { },
+ s => { },
+ d => { },
+ b => { },
+ c => { },
+ l => { },
+ f => { },
+ m => captured = m);
+
+ Assert.Equal(99.99m, captured);
+ }
+
+ [Fact]
+ public void AnyOf8_Is_WorksForAllTypes()
+ {
+ AnyOf value = 99.99m;
+
+ Assert.False(value.Is());
+ Assert.False(value.Is());
+ Assert.False(value.Is());
+ Assert.False(value.Is());
+ Assert.False(value.Is());
+ Assert.False(value.Is());
+ Assert.False(value.Is());
+ Assert.True(value.Is());
+ }
+
+ [Fact]
+ public void AnyOf8_As_WorksCorrectly()
+ {
+ AnyOf value = 99.99m;
+
+ Assert.Equal(99.99m, value.As());
+ Assert.Throws(() => value.As());
+ }
+
+ [Fact]
+ public void AnyOf8_TryGet_WorksCorrectly()
+ {
+ AnyOf value = 99.99m;
+
+ Assert.True(value.TryGet(out decimal d));
+ Assert.Equal(99.99m, d);
+ Assert.False(value.TryGet(out int _));
+ }
+
+ [Fact]
+ public void AnyOf8_GetMatchingTypes_ReturnsMatchingTypes()
+ {
+ AnyOf value = 99.99m;
+
+ var matchingTypes = value.GetMatchingTypes().ToList();
+
+ Assert.Single(matchingTypes);
+ Assert.Contains(typeof(decimal), matchingTypes);
+ }
+
+ [Fact]
+ public void AnyOf8_Equality_WorksCorrectly()
+ {
+ AnyOf val1 = 99.99m;
+ AnyOf val2 = 99.99m;
+ AnyOf val3 = 100m;
+
+ Assert.True(val1 == val2);
+ Assert.False(val1 != val2);
+ Assert.True(val1 != val3);
+ }
+
+ [Fact]
+ public void AnyOf8_ToString_ReturnsValueString()
+ {
+ AnyOf value = "hello";
+
+ Assert.Equal("hello", value.ToString());
+ }
+
+ #endregion
+
+ #region IAnyOf Interface Tests
+
+ [Fact]
+ public void AllAnyOfTypes_ImplementIAnyOf()
+ {
+ IAnyOf anyOf2 = (AnyOf)42;
+ IAnyOf anyOf3 = (AnyOf)42;
+ IAnyOf anyOf4 = (AnyOf)42;
+ IAnyOf anyOf5 = (AnyOf)42;
+ IAnyOf anyOf6 = (AnyOf)42;
+ IAnyOf anyOf7 = (AnyOf)42;
+ IAnyOf anyOf8 = (AnyOf)42;
+
+ Assert.Equal(42, anyOf2.Value);
+ Assert.Contains(0, anyOf2.TypeIndices);
+
+ Assert.Equal(42, anyOf3.Value);
+ Assert.Equal(42, anyOf4.Value);
+ Assert.Equal(42, anyOf5.Value);
+ Assert.Equal(42, anyOf6.Value);
+ Assert.Equal(42, anyOf7.Value);
+ Assert.Equal(42, anyOf8.Value);
+ }
+
+ #endregion
+
+ #region Inheritance/Polymorphism Tests
+
+ [Fact]
+ public void AnyOf_GetMatchingTypes_IncludesBaseTypes()
+ {
+ // ArgumentException derives from Exception
+ AnyOf value = new ArgumentException("test");
+
+ var matchingTypes = value.GetMatchingTypes().ToList();
+
+ // Both Exception (base) and the actual type should match
+ Assert.Contains(typeof(Exception), matchingTypes);
+ }
+
+ [Fact]
+ public void AnyOf_Is_WorksWithDerivedTypes()
+ {
+ AnyOf value = new ArgumentException("test");
+
+ Assert.True(value.Is());
+ Assert.True(value.Is());
+ Assert.False(value.Is());
+ }
+
+ [Fact]
+ public void AnyOf_As_WorksWithDerivedTypes()
+ {
+ AnyOf value = new ArgumentException("test");
+
+ Assert.IsType(value.As());
+ Assert.IsType(value.As());
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Cortex.Tests/Types/Tests/OneOfTests.cs b/src/Cortex.Tests/Types/Tests/OneOfTests.cs
new file mode 100644
index 0000000..cb8f04b
--- /dev/null
+++ b/src/Cortex.Tests/Types/Tests/OneOfTests.cs
@@ -0,0 +1,571 @@
+using Cortex.Types;
+
+namespace Cortex.Tests.Types.Tests
+{
+ public class OneOfTests
+ {
+ #region OneOf Tests
+
+ [Fact]
+ public void OneOf2_ImplicitConversion_FromT1_SetsCorrectTypeIndex()
+ {
+ OneOf value = 42;
+
+ Assert.Equal(0, value.TypeIndex);
+ Assert.Equal(42, value.Value);
+ }
+
+ [Fact]
+ public void OneOf2_ImplicitConversion_FromT2_SetsCorrectTypeIndex()
+ {
+ OneOf value = "hello";
+
+ Assert.Equal(1, value.TypeIndex);
+ Assert.Equal("hello", value.Value);
+ }
+
+ [Fact]
+ public void OneOf2_Is_ReturnsTrue_WhenTypeMatches()
+ {
+ OneOf value = 42;
+
+ Assert.True(value.Is());
+ Assert.False(value.Is());
+ }
+
+ [Fact]
+ public void OneOf2_As_ReturnsValue_WhenTypeMatches()
+ {
+ OneOf value = 42;
+
+ Assert.Equal(42, value.As());
+ }
+
+ [Fact]
+ public void OneOf2_As_ThrowsInvalidCastException_WhenTypeMismatch()
+ {
+ OneOf value = 42;
+
+ Assert.Throws(() => value.As());
+ }
+
+ [Fact]
+ public void OneOf2_TryGet_ReturnsTrue_WhenTypeMatches()
+ {
+ OneOf value = 42;
+
+ Assert.True(value.TryGet(out int result));
+ Assert.Equal(42, result);
+ }
+
+ [Fact]
+ public void OneOf2_TryGet_ReturnsFalse_WhenTypeMismatch()
+ {
+ OneOf value = 42;
+
+ Assert.False(value.TryGet(out string? result));
+ }
+
+ [Fact]
+ public void OneOf2_Match_ExecutesCorrectHandler()
+ {
+ OneOf intValue = 42;
+ OneOf stringValue = "hello";
+
+ var intResult = intValue.Match(
+ i => $"int: {i}",
+ s => $"string: {s}");
+
+ var stringResult = stringValue.Match(
+ i => $"int: {i}",
+ s => $"string: {s}");
+
+ Assert.Equal("int: 42", intResult);
+ Assert.Equal("string: hello", stringResult);
+ }
+
+ [Fact]
+ public void OneOf2_Switch_ExecutesCorrectAction()
+ {
+ OneOf value = 42;
+ int? capturedInt = null;
+ string? capturedString = null;
+
+ value.Switch(
+ i => capturedInt = i,
+ s => capturedString = s);
+
+ Assert.Equal(42, capturedInt);
+ Assert.Null(capturedString);
+ }
+
+ [Fact]
+ public void OneOf2_Equals_ReturnsTrue_ForSameValues()
+ {
+ OneOf value1 = 42;
+ OneOf value2 = 42;
+
+ Assert.Equal(value1, value2);
+ Assert.True(value1 == value2);
+ Assert.False(value1 != value2);
+ }
+
+ [Fact]
+ public void OneOf2_Equals_ReturnsFalse_ForDifferentValues()
+ {
+ OneOf value1 = 42;
+ OneOf value2 = "hello";
+
+ Assert.NotEqual(value1, value2);
+ }
+
+ [Fact]
+ public void OneOf2_ToString_ReturnsValueString()
+ {
+ OneOf value = 42;
+
+ Assert.Equal("42", value.ToString());
+ }
+
+ #endregion
+
+ #region OneOf Tests
+
+ [Fact]
+ public void OneOf3_ImplicitConversion_FromEachType_SetsCorrectTypeIndex()
+ {
+ OneOf intVal = 42;
+ OneOf strVal = "hello";
+ OneOf dblVal = 3.14;
+
+ Assert.Equal(0, intVal.TypeIndex);
+ Assert.Equal(1, strVal.TypeIndex);
+ Assert.Equal(2, dblVal.TypeIndex);
+ }
+
+ [Fact]
+ public void OneOf3_Match_ExecutesCorrectHandler()
+ {
+ OneOf value = 3.14;
+
+ var result = value.Match(
+ i => "int",
+ s => "string",
+ d => "double");
+
+ Assert.Equal("double", result);
+ }
+
+ [Fact]
+ public void OneOf3_Switch_ExecutesCorrectAction()
+ {
+ OneOf value = "hello";
+ string? captured = null;
+
+ value.Switch(
+ i => { },
+ s => captured = s,
+ d => { });
+
+ Assert.Equal("hello", captured);
+ }
+
+ #endregion
+
+ #region OneOf Tests
+
+ [Fact]
+ public void OneOf4_ImplicitConversion_FromEachType_SetsCorrectTypeIndex()
+ {
+ OneOf val1 = 42;
+ OneOf val2 = "hello";
+ OneOf val3 = 3.14;
+ OneOf val4 = true;
+
+ Assert.Equal(0, val1.TypeIndex);
+ Assert.Equal(1, val2.TypeIndex);
+ Assert.Equal(2, val3.TypeIndex);
+ Assert.Equal(3, val4.TypeIndex);
+ }
+
+ [Fact]
+ public void OneOf4_Match_ExecutesCorrectHandler()
+ {
+ OneOf value = true;
+
+ var result = value.Match(
+ i => "int",
+ s => "string",
+ d => "double",
+ b => "bool");
+
+ Assert.Equal("bool", result);
+ }
+
+ #endregion
+
+ #region OneOf Tests
+
+ [Fact]
+ public void OneOf5_ImplicitConversion_FromEachType_SetsCorrectTypeIndex()
+ {
+ OneOf val1 = 42;
+ OneOf val2 = "hello";
+ OneOf val3 = 3.14;
+ OneOf val4 = true;
+ OneOf val5 = 'x';
+
+ Assert.Equal(0, val1.TypeIndex);
+ Assert.Equal(1, val2.TypeIndex);
+ Assert.Equal(2, val3.TypeIndex);
+ Assert.Equal(3, val4.TypeIndex);
+ Assert.Equal(4, val5.TypeIndex);
+ }
+
+ [Fact]
+ public void OneOf5_Match_ExecutesCorrectHandler()
+ {
+ OneOf value = 'x';
+
+ var result = value.Match(
+ i => "int",
+ s => "string",
+ d => "double",
+ b => "bool",
+ c => "char");
+
+ Assert.Equal("char", result);
+ }
+
+ [Fact]
+ public void OneOf5_Switch_ExecutesCorrectAction()
+ {
+ OneOf value = 'x';
+ char? captured = null;
+
+ value.Switch(
+ i => { },
+ s => { },
+ d => { },
+ b => { },
+ c => captured = c);
+
+ Assert.Equal('x', captured);
+ }
+
+ [Fact]
+ public void OneOf5_TryGet_WorksCorrectly()
+ {
+ OneOf value = 3.14;
+
+ Assert.True(value.TryGet(out double d));
+ Assert.Equal(3.14, d);
+ Assert.False(value.TryGet(out int _));
+ }
+
+ [Fact]
+ public void OneOf5_Equals_WorksCorrectly()
+ {
+ OneOf val1 = 'x';
+ OneOf val2 = 'x';
+ OneOf val3 = 'y';
+
+ Assert.Equal(val1, val2);
+ Assert.NotEqual(val1, val3);
+ }
+
+ #endregion
+
+ #region OneOf Tests
+
+ [Fact]
+ public void OneOf6_ImplicitConversion_FromEachType_SetsCorrectTypeIndex()
+ {
+ OneOf val1 = 42;
+ OneOf val2 = "hello";
+ OneOf val3 = 3.14;
+ OneOf val4 = true;
+ OneOf val5 = 'x';
+ OneOf val6 = 100L;
+
+ Assert.Equal(0, val1.TypeIndex);
+ Assert.Equal(1, val2.TypeIndex);
+ Assert.Equal(2, val3.TypeIndex);
+ Assert.Equal(3, val4.TypeIndex);
+ Assert.Equal(4, val5.TypeIndex);
+ Assert.Equal(5, val6.TypeIndex);
+ }
+
+ [Fact]
+ public void OneOf6_Match_ExecutesCorrectHandler()
+ {
+ OneOf value = 100L;
+
+ var result = value.Match(
+ i => "int",
+ s => "string",
+ d => "double",
+ b => "bool",
+ c => "char",
+ l => "long");
+
+ Assert.Equal("long", result);
+ }
+
+ [Fact]
+ public void OneOf6_Switch_ExecutesCorrectAction()
+ {
+ OneOf value = 100L;
+ long? captured = null;
+
+ value.Switch(
+ i => { },
+ s => { },
+ d => { },
+ b => { },
+ c => { },
+ l => captured = l);
+
+ Assert.Equal(100L, captured);
+ }
+
+ #endregion
+
+ #region OneOf Tests
+
+ [Fact]
+ public void OneOf7_ImplicitConversion_FromEachType_SetsCorrectTypeIndex()
+ {
+ OneOf val1 = 42;
+ OneOf val2 = "hello";
+ OneOf val3 = 3.14;
+ OneOf val4 = true;
+ OneOf val5 = 'x';
+ OneOf val6 = 100L;
+ OneOf val7 = 1.5f;
+
+ Assert.Equal(0, val1.TypeIndex);
+ Assert.Equal(1, val2.TypeIndex);
+ Assert.Equal(2, val3.TypeIndex);
+ Assert.Equal(3, val4.TypeIndex);
+ Assert.Equal(4, val5.TypeIndex);
+ Assert.Equal(5, val6.TypeIndex);
+ Assert.Equal(6, val7.TypeIndex);
+ }
+
+ [Fact]
+ public void OneOf7_Match_ExecutesCorrectHandler()
+ {
+ OneOf value = 1.5f;
+
+ var result = value.Match(
+ i => "int",
+ s => "string",
+ d => "double",
+ b => "bool",
+ c => "char",
+ l => "long",
+ f => "float");
+
+ Assert.Equal("float", result);
+ }
+
+ [Fact]
+ public void OneOf7_Switch_ExecutesCorrectAction()
+ {
+ OneOf value = 1.5f;
+ float? captured = null;
+
+ value.Switch(
+ i => { },
+ s => { },
+ d => { },
+ b => { },
+ c => { },
+ l => { },
+ f => captured = f);
+
+ Assert.Equal(1.5f, captured);
+ }
+
+ [Fact]
+ public void OneOf7_Equality_WorksCorrectly()
+ {
+ OneOf val1 = 1.5f;
+ OneOf val2 = 1.5f;
+
+ Assert.True(val1 == val2);
+ Assert.False(val1 != val2);
+ Assert.Equal(val1.GetHashCode(), val2.GetHashCode());
+ }
+
+ #endregion
+
+ #region OneOf Tests
+
+ [Fact]
+ public void OneOf8_ImplicitConversion_FromEachType_SetsCorrectTypeIndex()
+ {
+ OneOf val1 = 42;
+ OneOf val2 = "hello";
+ OneOf val3 = 3.14;
+ OneOf val4 = true;
+ OneOf val5 = 'x';
+ OneOf val6 = 100L;
+ OneOf val7 = 1.5f;
+ OneOf val8 = 99.99m;
+
+ Assert.Equal(0, val1.TypeIndex);
+ Assert.Equal(1, val2.TypeIndex);
+ Assert.Equal(2, val3.TypeIndex);
+ Assert.Equal(3, val4.TypeIndex);
+ Assert.Equal(4, val5.TypeIndex);
+ Assert.Equal(5, val6.TypeIndex);
+ Assert.Equal(6, val7.TypeIndex);
+ Assert.Equal(7, val8.TypeIndex);
+ }
+
+ [Fact]
+ public void OneOf8_Match_ExecutesCorrectHandler()
+ {
+ OneOf value = 99.99m;
+
+ var result = value.Match(
+ i => "int",
+ s => "string",
+ d => "double",
+ b => "bool",
+ c => "char",
+ l => "long",
+ f => "float",
+ m => "decimal");
+
+ Assert.Equal("decimal", result);
+ }
+
+ [Fact]
+ public void OneOf8_Switch_ExecutesCorrectAction()
+ {
+ OneOf value = 99.99m;
+ decimal? captured = null;
+
+ value.Switch(
+ i => { },
+ s => { },
+ d => { },
+ b => { },
+ c => { },
+ l => { },
+ f => { },
+ m => captured = m);
+
+ Assert.Equal(99.99m, captured);
+ }
+
+ [Fact]
+ public void OneOf8_Is_WorksForAllTypes()
+ {
+ OneOf value = 99.99m;
+
+ Assert.False(value.Is());
+ Assert.False(value.Is());
+ Assert.False(value.Is());
+ Assert.False(value.Is());
+ Assert.False(value.Is());
+ Assert.False(value.Is());
+ Assert.False(value.Is());
+ Assert.True(value.Is());
+ }
+
+ [Fact]
+ public void OneOf8_As_WorksCorrectly()
+ {
+ OneOf value = 99.99m;
+
+ Assert.Equal(99.99m, value.As());
+ Assert.Throws(() => value.As());
+ }
+
+ [Fact]
+ public void OneOf8_TryGet_WorksCorrectly()
+ {
+ OneOf value = 99.99m;
+
+ Assert.True(value.TryGet(out decimal d));
+ Assert.Equal(99.99m, d);
+ Assert.False(value.TryGet(out int _));
+ }
+
+ [Fact]
+ public void OneOf8_Equality_WorksCorrectly()
+ {
+ OneOf val1 = 99.99m;
+ OneOf val2 = 99.99m;
+ OneOf val3 = 100m;
+
+ Assert.True(val1 == val2);
+ Assert.False(val1 != val2);
+ Assert.True(val1 != val3);
+ Assert.Equal(val1.GetHashCode(), val2.GetHashCode());
+ }
+
+ [Fact]
+ public void OneOf8_ToString_ReturnsValueString()
+ {
+ OneOf value = "hello";
+
+ Assert.Equal("hello", value.ToString());
+ }
+
+ #endregion
+
+ #region IOneOf Interface Tests
+
+ [Fact]
+ public void AllOneOfTypes_ImplementIOneOf()
+ {
+ IOneOf oneOf2 = (OneOf)42;
+ IOneOf oneOf3 = (OneOf)42;
+ IOneOf oneOf4 = (OneOf)42;
+ IOneOf oneOf5 = (OneOf)42;
+ IOneOf oneOf6 = (OneOf)42;
+ IOneOf oneOf7 = (OneOf)42;
+ IOneOf oneOf8 = (OneOf)42;
+
+ Assert.Equal(42, oneOf2.Value);
+ Assert.Equal(0, oneOf2.TypeIndex);
+
+ Assert.Equal(42, oneOf3.Value);
+ Assert.Equal(42, oneOf4.Value);
+ Assert.Equal(42, oneOf5.Value);
+ Assert.Equal(42, oneOf6.Value);
+ Assert.Equal(42, oneOf7.Value);
+ Assert.Equal(42, oneOf8.Value);
+ }
+
+ #endregion
+
+ #region Inheritance Tests
+
+ [Fact]
+ public void OneOf_Is_WorksWithDerivedTypes()
+ {
+ OneOf value = new ArgumentException("test");
+
+ Assert.True(value.Is());
+ Assert.True(value.Is());
+ Assert.False(value.Is());
+ }
+
+ [Fact]
+ public void OneOf_As_WorksWithDerivedTypes()
+ {
+ OneOf value = new ArgumentException("test");
+
+ Assert.IsType(value.As());
+ Assert.IsType(value.As());
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Cortex.Tests/Types/Tests/Result2Tests.cs b/src/Cortex.Tests/Types/Tests/Result2Tests.cs
new file mode 100644
index 0000000..49c32fd
--- /dev/null
+++ b/src/Cortex.Tests/Types/Tests/Result2Tests.cs
@@ -0,0 +1,665 @@
+using Cortex.Types;
+
+namespace Cortex.Tests.Types.Tests
+{
+ public class Result2Tests
+ {
+ #region Custom Error Type for Testing
+
+ private record TestError(string Code, string Description);
+
+ #endregion
+
+ #region Creation Tests
+
+ [Fact]
+ public void Success_CreatesSuccessfulResult()
+ {
+ // Act
+ var result = Result.Success(42);
+
+ // Assert
+ Assert.True(result.IsSuccess);
+ Assert.False(result.IsFailure);
+ Assert.Equal(42, result.Value);
+ }
+
+ [Fact]
+ public void Failure_CreatesFailedResult()
+ {
+ // Arrange
+ var error = new TestError("ERR001", "Test error");
+
+ // Act
+ var result = Result.Failure(error);
+
+ // Assert
+ Assert.False(result.IsSuccess);
+ Assert.True(result.IsFailure);
+ Assert.Equal(error, result.Error);
+ }
+
+ #endregion
+
+ #region Implicit Conversion Tests
+
+ [Fact]
+ public void ImplicitConversion_FromValue_CreatesSuccessResult()
+ {
+ // Act
+ Result result = "test value";
+
+ // Assert
+ Assert.True(result.IsSuccess);
+ Assert.Equal("test value", result.Value);
+ }
+
+ #endregion
+
+ #region Value Access Tests
+
+ [Fact]
+ public void Value_OnSuccess_ReturnsValue()
+ {
+ // Arrange
+ var result = Result.Success(42);
+
+ // Act & Assert
+ Assert.Equal(42, result.Value);
+ }
+
+ [Fact]
+ public void Value_OnFailure_ThrowsInvalidOperationException()
+ {
+ // Arrange
+ var result = Result.Failure(new TestError("ERR", "Error"));
+
+ // Act & Assert
+ var exception = Assert.Throws(() => result.Value);
+ Assert.Contains("Cannot access Value", exception.Message);
+ }
+
+ [Fact]
+ public void Error_OnFailure_ReturnsError()
+ {
+ // Arrange
+ var error = new TestError("ERR001", "Test error");
+ var result = Result.Failure(error);
+
+ // Act & Assert
+ Assert.Equal(error, result.Error);
+ }
+
+ [Fact]
+ public void Error_OnSuccess_ThrowsInvalidOperationException()
+ {
+ // Arrange
+ var result = Result.Success(42);
+
+ // Act & Assert
+ var exception = Assert.Throws(() => result.Error);
+ Assert.Contains("Cannot access Error", exception.Message);
+ }
+
+ #endregion
+
+ #region TryGet Tests
+
+ [Fact]
+ public void TryGetValue_OnSuccess_ReturnsTrueAndValue()
+ {
+ // Arrange
+ var result = Result.Success(42);
+
+ // Act
+ var success = result.TryGetValue(out var value);
+
+ // Assert
+ Assert.True(success);
+ Assert.Equal(42, value);
+ }
+
+ [Fact]
+ public void TryGetValue_OnFailure_ReturnsFalse()
+ {
+ // Arrange
+ var result = Result.Failure(new TestError("ERR", "Error"));
+
+ // Act
+ var success = result.TryGetValue(out var value);
+
+ // Assert
+ Assert.False(success);
+ Assert.Equal(default, value);
+ }
+
+ [Fact]
+ public void TryGetError_OnFailure_ReturnsTrueAndError()
+ {
+ // Arrange
+ var error = new TestError("ERR001", "Test error");
+ var result = Result.Failure(error);
+
+ // Act
+ var hasError = result.TryGetError(out var retrievedError);
+
+ // Assert
+ Assert.True(hasError);
+ Assert.Equal(error, retrievedError);
+ }
+
+ [Fact]
+ public void TryGetError_OnSuccess_ReturnsFalse()
+ {
+ // Arrange
+ var result = Result.Success(42);
+
+ // Act
+ var hasError = result.TryGetError(out var error);
+
+ // Assert
+ Assert.False(hasError);
+ Assert.Null(error);
+ }
+
+ #endregion
+
+ #region GetValueOrDefault Tests
+
+ [Fact]
+ public void GetValueOrDefault_OnSuccess_ReturnsValue()
+ {
+ // Arrange
+ var result = Result.Success(42);
+
+ // Act
+ var value = result.GetValueOrDefault(0);
+
+ // Assert
+ Assert.Equal(42, value);
+ }
+
+ [Fact]
+ public void GetValueOrDefault_OnFailure_ReturnsDefault()
+ {
+ // Arrange
+ var result = Result.Failure(new TestError("ERR", "Error"));
+
+ // Act
+ var value = result.GetValueOrDefault(99);
+
+ // Assert
+ Assert.Equal(99, value);
+ }
+
+ [Fact]
+ public void GetValueOrDefault_WithFactory_OnFailure_CallsFactory()
+ {
+ // Arrange
+ var result = Result.Failure(new TestError("ERR", "Error"));
+
+ // Act
+ var value = result.GetValueOrDefault(() => 99);
+
+ // Assert
+ Assert.Equal(99, value);
+ }
+
+ [Fact]
+ public void GetValueOrDefault_WithErrorHandler_OnFailure_PassesError()
+ {
+ // Arrange
+ var error = new TestError("ERR001", "Test error");
+ var result = Result.Failure(error);
+ TestError? capturedError = null;
+
+ // Act
+ var value = result.GetValueOrDefault(e => { capturedError = e; return "default"; });
+
+ // Assert
+ Assert.Equal("default", value);
+ Assert.Equal(error, capturedError);
+ }
+
+ #endregion
+
+ #region Match Tests
+
+ [Fact]
+ public void Match_OnSuccess_ExecutesSuccessHandler()
+ {
+ // Arrange
+ var result = Result.Success(42);
+
+ // Act
+ var output = result.Match(
+ onSuccess: v => $"Success: {v}",
+ onFailure: e => $"Failure: {e.Code}");
+
+ // Assert
+ Assert.Equal("Success: 42", output);
+ }
+
+ [Fact]
+ public void Match_OnFailure_ExecutesFailureHandler()
+ {
+ // Arrange
+ var result = Result.Failure(new TestError("ERR001", "Error"));
+
+ // Act
+ var output = result.Match(
+ onSuccess: v => $"Success: {v}",
+ onFailure: e => $"Failure: {e.Code}");
+
+ // Assert
+ Assert.Equal("Failure: ERR001", output);
+ }
+
+ #endregion
+
+ #region Switch Tests
+
+ [Fact]
+ public void Switch_OnSuccess_ExecutesSuccessAction()
+ {
+ // Arrange
+ var result = Result.Success(42);
+ int? capturedValue = null;
+ TestError? capturedError = null;
+
+ // Act
+ result.Switch(
+ onSuccess: v => capturedValue = v,
+ onFailure: e => capturedError = e);
+
+ // Assert
+ Assert.Equal(42, capturedValue);
+ Assert.Null(capturedError);
+ }
+
+ [Fact]
+ public void Switch_OnFailure_ExecutesFailureAction()
+ {
+ // Arrange
+ var error = new TestError("ERR001", "Test error");
+ var result = Result.Failure(error);
+ int? capturedValue = null;
+ TestError? capturedError = null;
+
+ // Act
+ result.Switch(
+ onSuccess: v => capturedValue = v,
+ onFailure: e => capturedError = e);
+
+ // Assert
+ Assert.Null(capturedValue);
+ Assert.Equal(error, capturedError);
+ }
+
+ #endregion
+
+ #region Map Tests
+
+ [Fact]
+ public void Map_OnSuccess_TransformsValue()
+ {
+ // Arrange
+ var result = Result.Success(42);
+
+ // Act
+ var mapped = result.Map(v => v.ToString());
+
+ // Assert
+ Assert.True(mapped.IsSuccess);
+ Assert.Equal("42", mapped.Value);
+ }
+
+ [Fact]
+ public void Map_OnFailure_PreservesError()
+ {
+ // Arrange
+ var error = new TestError("ERR001", "Test error");
+ var result = Result.Failure(error);
+
+ // Act
+ var mapped = result.Map(v => v.ToString());
+
+ // Assert
+ Assert.True(mapped.IsFailure);
+ Assert.Equal(error, mapped.Error);
+ }
+
+ [Fact]
+ public void MapError_OnFailure_TransformsError()
+ {
+ // Arrange
+ var result = Result.Failure(new TestError("ERR001", "Original"));
+
+ // Act
+ var mapped = result.MapError(e => new TestError(e.Code, $"Mapped: {e.Description}"));
+
+ // Assert
+ Assert.True(mapped.IsFailure);
+ Assert.Equal("Mapped: Original", mapped.Error.Description);
+ }
+
+ [Fact]
+ public void MapError_CanChangeErrorType()
+ {
+ // Arrange
+ var result = Result.Failure(new TestError("ERR001", "Test"));
+
+ // Act
+ var mapped = result.MapError(e => e.Code); // Transform to string error
+
+ // Assert
+ Assert.True(mapped.IsFailure);
+ Assert.Equal("ERR001", mapped.Error);
+ }
+
+ [Fact]
+ public void MapError_OnSuccess_PreservesValue()
+ {
+ // Arrange
+ var result = Result