Make Optional<T> into readonly struct to avoid heap allocations

This commit is contained in:
Daniel Cronqvist 2024-12-02 22:45:14 +01:00
parent de41fb5508
commit 92702a512d
35 changed files with 177 additions and 205 deletions

View file

@ -35,8 +35,7 @@ public static partial class DotTiledAssert
AssertEqual(expected.X, actual.X, nameof(TileLayer.X));
AssertEqual(expected.Y, actual.Y, nameof(TileLayer.Y));
Assert.NotNull(actual.Data);
AssertData(expected.Data, actual.Data);
AssertOptionalsEqual(expected.Data, actual.Data, nameof(TileLayer.Data), AssertData);
}
private static void AssertLayer(ObjectLayer expected, ObjectLayer actual)
@ -60,8 +59,7 @@ public static partial class DotTiledAssert
AssertEqual(expected.X, actual.X, nameof(ImageLayer.X));
AssertEqual(expected.Y, actual.Y, nameof(ImageLayer.Y));
Assert.NotNull(actual.Image);
AssertImage(expected.Image, actual.Image);
AssertOptionalsEqual(expected.Image, actual.Image, nameof(ImageLayer.Image), AssertImage);
}
private static void AssertLayer(Group expected, Group actual)

View file

@ -33,12 +33,6 @@ public static partial class DotTiledAssert
string nameof,
Action<T, T> assertEqual)
{
if (expected is null)
{
Assert.Null(actual);
return;
}
if (expected.HasValue)
{
Assert.True(actual.HasValue, $"Expected {nameof} to have a value");
@ -51,12 +45,6 @@ public static partial class DotTiledAssert
internal static void AssertEqual<T>(Optional<T> expected, Optional<T> actual, string nameof)
{
if (expected is null)
{
Assert.Null(actual);
return;
}
if (expected.HasValue)
{
Assert.True(actual.HasValue, $"Expected {nameof} to have a value");

View file

@ -58,7 +58,7 @@ public partial class TestData
new IntProperty { Name = "intprop", Value = 8 },
new ObjectProperty { Name = "objectprop", Value = 5 },
new StringProperty { Name = "stringprop", Value = "This is a string, hello world!" },
new ColorProperty { Name = "unsetcolorprop", Value = Optional<Color>.Empty }
new ColorProperty { Name = "unsetcolorprop", Value = Optional.Empty }
]
};
}

View file

@ -59,30 +59,6 @@ public class OptionalTests
Assert.Equal(expectedValue, optional.Value);
}
[Fact]
public void ImplicitConversion_FromOptionalToValue_ShouldReturnValue_WhenHasValueIsTrue()
{
// Arrange
int expectedValue = 10;
var optional = new Optional<int>(expectedValue);
// Act
int value = optional;
// Assert
Assert.Equal(expectedValue, value);
}
[Fact]
public void ImplicitConversion_FromOptionalToValue_ShouldThrowException_WhenHasValueIsFalse()
{
// Arrange
var optional = new Optional<int>();
// Act & Assert
_ = Assert.Throws<InvalidOperationException>(() => { int value = optional; });
}
// ToString Method Tests
[Fact]
@ -237,18 +213,6 @@ public class OptionalTests
_ = Assert.Throws<InvalidOperationException>(() => optional.Value);
}
[Fact]
public void ImplicitConversion_WhenHasValueIsFalse_ShouldThrowInvalidOperationException()
{
// Arrange
var optional = new Optional<int>();
// Act & Assert
_ = Assert.Throws<InvalidOperationException>(() => { int value = optional; });
}
// Edge Cases
[Fact]
public void EmptyOptionalEquality_ShouldReturnTrue()
{

View file

@ -71,8 +71,8 @@ public class LoaderTests
""");
var resourceCache = Substitute.For<IResourceCache>();
resourceCache.GetTileset(Arg.Any<string>()).Returns(Optional<Tileset>.Empty);
resourceCache.GetTemplate(Arg.Any<string>()).Returns(Optional<Template>.Empty);
resourceCache.GetTileset(Arg.Any<string>()).Returns(Optional.Empty);
resourceCache.GetTemplate(Arg.Any<string>()).Returns(Optional.Empty);
var customTypeDefinitions = Enumerable.Empty<ICustomTypeDefinition>();
var loader = new Loader(resourceReader, resourceCache, customTypeDefinitions);
@ -134,8 +134,8 @@ public class LoaderTests
""");
var resourceCache = Substitute.For<IResourceCache>();
resourceCache.GetTileset(Arg.Any<string>()).Returns(Optional<Tileset>.Empty);
resourceCache.GetTemplate(Arg.Any<string>()).Returns(Optional<Template>.Empty);
resourceCache.GetTileset(Arg.Any<string>()).Returns(Optional.Empty);
resourceCache.GetTemplate(Arg.Any<string>()).Returns(Optional.Empty);
var customTypeDefinitions = Enumerable.Empty<ICustomTypeDefinition>();
var loader = new Loader(resourceReader, resourceCache, customTypeDefinitions);
@ -219,7 +219,7 @@ public class LoaderTests
""");
var resourceCache = Substitute.For<IResourceCache>();
resourceCache.GetTileset(Arg.Any<string>()).Returns(Optional<Tileset>.Empty);
resourceCache.GetTileset(Arg.Any<string>()).Returns(Optional.Empty);
resourceCache.GetTemplate("template.tx").Returns(new Optional<Template>(new Template
{
Object = new PolygonObject

View file

@ -39,7 +39,7 @@ public partial class MapReaderTests
return new Optional<ICustomTypeDefinition>(ctd);
}
return Optional<ICustomTypeDefinition>.Empty;
return Optional.Empty;
}
using var mapReader = new MapReader(mapString, ResolveTileset, ResolveTemplate, ResolveCustomType);

View file

@ -35,7 +35,7 @@ public partial class TmjMapReaderTests
return new Optional<ICustomTypeDefinition>(ctd);
}
return Optional<ICustomTypeDefinition>.Empty;
return Optional.Empty;
}
using var mapReader = new TmjMapReader(json, ResolveTileset, ResolveTemplate, ResolveCustomType);

View file

@ -35,7 +35,7 @@ public partial class TmxMapReaderTests
return new Optional<ICustomTypeDefinition>(ctd);
}
return Optional<ICustomTypeDefinition>.Empty;
return Optional.Empty;
}
using var mapReader = new TmxMapReader(reader, ResolveTileset, ResolveTemplate, ResolveCustomType);