diff --git a/src/Graphics/src/Graphics/Color.cs b/src/Graphics/src/Graphics/Color.cs index 866d740377c2..8a7c1d343e7a 100644 --- a/src/Graphics/src/Graphics/Color.cs +++ b/src/Graphics/src/Graphics/Color.cs @@ -11,10 +11,15 @@ namespace Microsoft.Maui.Graphics /// /// Represents an RGBA color with floating-point components in the range of 0.0 to 1.0. /// + /// + /// is a sealed record type, so equality (via , ==, and !=) + /// is always value-based, comparing the underlying ARGB representation regardless of how the instance was created. + /// Sealing prevents subclassing, which guarantees this value-based equality can never be silently broken by a derived type. + /// [DebuggerDisplay("Red={Red}, Green={Green}, Blue={Blue}, Alpha={Alpha}")] [TypeConverter(typeof(Converters.ColorTypeConverter))] [ImmutableObject(true)] - public record class Color + public sealed record class Color { /// /// The red component of the color, ranging from 0.0 to 1.0. @@ -119,7 +124,7 @@ public override string ToString() /// /// Determines whether the specified is equal to the current color using byte-precision comparison. /// - public virtual bool Equals(Color? other) + public bool Equals(Color? other) { if (other is null) return false; diff --git a/src/Graphics/src/Graphics/PublicAPI/net-android/PublicAPI.Unshipped.txt b/src/Graphics/src/Graphics/PublicAPI/net-android/PublicAPI.Unshipped.txt index 52af5b2eb3e6..66174a2f4fec 100644 --- a/src/Graphics/src/Graphics/PublicAPI/net-android/PublicAPI.Unshipped.txt +++ b/src/Graphics/src/Graphics/PublicAPI/net-android/PublicAPI.Unshipped.txt @@ -1,12 +1,9 @@ #nullable enable -Microsoft.Maui.Graphics.Color.Color(Microsoft.Maui.Graphics.Color! original) -> void override Microsoft.Maui.Graphics.Color.Equals(object? obj) -> bool static Microsoft.Maui.Graphics.Color.operator !=(Microsoft.Maui.Graphics.Color? left, Microsoft.Maui.Graphics.Color? right) -> bool static Microsoft.Maui.Graphics.Color.operator ==(Microsoft.Maui.Graphics.Color? left, Microsoft.Maui.Graphics.Color? right) -> bool -virtual Microsoft.Maui.Graphics.Color.$() -> Microsoft.Maui.Graphics.Color! -virtual Microsoft.Maui.Graphics.Color.EqualityContract.get -> System.Type! -virtual Microsoft.Maui.Graphics.Color.PrintMembers(System.Text.StringBuilder! builder) -> bool -virtual Microsoft.Maui.Graphics.Color.Equals(Microsoft.Maui.Graphics.Color? other) -> bool +Microsoft.Maui.Graphics.Color.$() -> Microsoft.Maui.Graphics.Color! +Microsoft.Maui.Graphics.Color.Equals(Microsoft.Maui.Graphics.Color? other) -> bool Microsoft.Maui.Graphics.Color.AddLuminosity(float delta) -> Microsoft.Maui.Graphics.Color! Microsoft.Maui.Graphics.Color.ToArgbHex(bool includeAlpha = false) -> string! Microsoft.Maui.Graphics.Color.ToRgbaHex(bool includeAlpha = false) -> string! diff --git a/src/Graphics/src/Graphics/PublicAPI/net-ios/PublicAPI.Unshipped.txt b/src/Graphics/src/Graphics/PublicAPI/net-ios/PublicAPI.Unshipped.txt index b40576003686..15dd3ad7ed64 100644 --- a/src/Graphics/src/Graphics/PublicAPI/net-ios/PublicAPI.Unshipped.txt +++ b/src/Graphics/src/Graphics/PublicAPI/net-ios/PublicAPI.Unshipped.txt @@ -1,12 +1,9 @@ #nullable enable -Microsoft.Maui.Graphics.Color.Color(Microsoft.Maui.Graphics.Color! original) -> void override Microsoft.Maui.Graphics.Color.Equals(object? obj) -> bool static Microsoft.Maui.Graphics.Color.operator !=(Microsoft.Maui.Graphics.Color? left, Microsoft.Maui.Graphics.Color? right) -> bool static Microsoft.Maui.Graphics.Color.operator ==(Microsoft.Maui.Graphics.Color? left, Microsoft.Maui.Graphics.Color? right) -> bool -virtual Microsoft.Maui.Graphics.Color.$() -> Microsoft.Maui.Graphics.Color! -virtual Microsoft.Maui.Graphics.Color.EqualityContract.get -> System.Type! -virtual Microsoft.Maui.Graphics.Color.Equals(Microsoft.Maui.Graphics.Color? other) -> bool -virtual Microsoft.Maui.Graphics.Color.PrintMembers(System.Text.StringBuilder! builder) -> bool +Microsoft.Maui.Graphics.Color.$() -> Microsoft.Maui.Graphics.Color! +Microsoft.Maui.Graphics.Color.Equals(Microsoft.Maui.Graphics.Color? other) -> bool Microsoft.Maui.Graphics.Color.AsPaint() -> Microsoft.Maui.Graphics.Paint! Microsoft.Maui.Graphics.Color.MultiplyAlpha(float multiplyBy) -> Microsoft.Maui.Graphics.Color! Microsoft.Maui.Graphics.Color.WithAlpha(float alpha) -> Microsoft.Maui.Graphics.Color! diff --git a/src/Graphics/src/Graphics/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt b/src/Graphics/src/Graphics/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt index b40576003686..15dd3ad7ed64 100644 --- a/src/Graphics/src/Graphics/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt +++ b/src/Graphics/src/Graphics/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt @@ -1,12 +1,9 @@ #nullable enable -Microsoft.Maui.Graphics.Color.Color(Microsoft.Maui.Graphics.Color! original) -> void override Microsoft.Maui.Graphics.Color.Equals(object? obj) -> bool static Microsoft.Maui.Graphics.Color.operator !=(Microsoft.Maui.Graphics.Color? left, Microsoft.Maui.Graphics.Color? right) -> bool static Microsoft.Maui.Graphics.Color.operator ==(Microsoft.Maui.Graphics.Color? left, Microsoft.Maui.Graphics.Color? right) -> bool -virtual Microsoft.Maui.Graphics.Color.$() -> Microsoft.Maui.Graphics.Color! -virtual Microsoft.Maui.Graphics.Color.EqualityContract.get -> System.Type! -virtual Microsoft.Maui.Graphics.Color.Equals(Microsoft.Maui.Graphics.Color? other) -> bool -virtual Microsoft.Maui.Graphics.Color.PrintMembers(System.Text.StringBuilder! builder) -> bool +Microsoft.Maui.Graphics.Color.$() -> Microsoft.Maui.Graphics.Color! +Microsoft.Maui.Graphics.Color.Equals(Microsoft.Maui.Graphics.Color? other) -> bool Microsoft.Maui.Graphics.Color.AsPaint() -> Microsoft.Maui.Graphics.Paint! Microsoft.Maui.Graphics.Color.MultiplyAlpha(float multiplyBy) -> Microsoft.Maui.Graphics.Color! Microsoft.Maui.Graphics.Color.WithAlpha(float alpha) -> Microsoft.Maui.Graphics.Color! diff --git a/src/Graphics/src/Graphics/PublicAPI/net-macos/PublicAPI.Unshipped.txt b/src/Graphics/src/Graphics/PublicAPI/net-macos/PublicAPI.Unshipped.txt index 55c756b6c1a4..8e3286e35b4d 100644 --- a/src/Graphics/src/Graphics/PublicAPI/net-macos/PublicAPI.Unshipped.txt +++ b/src/Graphics/src/Graphics/PublicAPI/net-macos/PublicAPI.Unshipped.txt @@ -1,12 +1,9 @@ #nullable enable -Microsoft.Maui.Graphics.Color.Color(Microsoft.Maui.Graphics.Color! original) -> void override Microsoft.Maui.Graphics.Color.Equals(object? obj) -> bool static Microsoft.Maui.Graphics.Color.operator !=(Microsoft.Maui.Graphics.Color? left, Microsoft.Maui.Graphics.Color? right) -> bool static Microsoft.Maui.Graphics.Color.operator ==(Microsoft.Maui.Graphics.Color? left, Microsoft.Maui.Graphics.Color? right) -> bool -virtual Microsoft.Maui.Graphics.Color.$() -> Microsoft.Maui.Graphics.Color! -virtual Microsoft.Maui.Graphics.Color.EqualityContract.get -> System.Type! -virtual Microsoft.Maui.Graphics.Color.PrintMembers(System.Text.StringBuilder! builder) -> bool -virtual Microsoft.Maui.Graphics.Color.Equals(Microsoft.Maui.Graphics.Color? other) -> bool +Microsoft.Maui.Graphics.Color.$() -> Microsoft.Maui.Graphics.Color! +Microsoft.Maui.Graphics.Color.Equals(Microsoft.Maui.Graphics.Color? other) -> bool Microsoft.Maui.Graphics.Color.AddLuminosity(float delta) -> Microsoft.Maui.Graphics.Color! Microsoft.Maui.Graphics.Color.GetComplementary() -> Microsoft.Maui.Graphics.Color! Microsoft.Maui.Graphics.Color.ToArgbHex(bool includeAlpha = false) -> string! diff --git a/src/Graphics/src/Graphics/PublicAPI/net-tizen/PublicAPI.Unshipped.txt b/src/Graphics/src/Graphics/PublicAPI/net-tizen/PublicAPI.Unshipped.txt index 55c756b6c1a4..8e3286e35b4d 100644 --- a/src/Graphics/src/Graphics/PublicAPI/net-tizen/PublicAPI.Unshipped.txt +++ b/src/Graphics/src/Graphics/PublicAPI/net-tizen/PublicAPI.Unshipped.txt @@ -1,12 +1,9 @@ #nullable enable -Microsoft.Maui.Graphics.Color.Color(Microsoft.Maui.Graphics.Color! original) -> void override Microsoft.Maui.Graphics.Color.Equals(object? obj) -> bool static Microsoft.Maui.Graphics.Color.operator !=(Microsoft.Maui.Graphics.Color? left, Microsoft.Maui.Graphics.Color? right) -> bool static Microsoft.Maui.Graphics.Color.operator ==(Microsoft.Maui.Graphics.Color? left, Microsoft.Maui.Graphics.Color? right) -> bool -virtual Microsoft.Maui.Graphics.Color.$() -> Microsoft.Maui.Graphics.Color! -virtual Microsoft.Maui.Graphics.Color.EqualityContract.get -> System.Type! -virtual Microsoft.Maui.Graphics.Color.PrintMembers(System.Text.StringBuilder! builder) -> bool -virtual Microsoft.Maui.Graphics.Color.Equals(Microsoft.Maui.Graphics.Color? other) -> bool +Microsoft.Maui.Graphics.Color.$() -> Microsoft.Maui.Graphics.Color! +Microsoft.Maui.Graphics.Color.Equals(Microsoft.Maui.Graphics.Color? other) -> bool Microsoft.Maui.Graphics.Color.AddLuminosity(float delta) -> Microsoft.Maui.Graphics.Color! Microsoft.Maui.Graphics.Color.GetComplementary() -> Microsoft.Maui.Graphics.Color! Microsoft.Maui.Graphics.Color.ToArgbHex(bool includeAlpha = false) -> string! diff --git a/src/Graphics/src/Graphics/PublicAPI/net-windows/PublicAPI.Unshipped.txt b/src/Graphics/src/Graphics/PublicAPI/net-windows/PublicAPI.Unshipped.txt index 55c756b6c1a4..8e3286e35b4d 100644 --- a/src/Graphics/src/Graphics/PublicAPI/net-windows/PublicAPI.Unshipped.txt +++ b/src/Graphics/src/Graphics/PublicAPI/net-windows/PublicAPI.Unshipped.txt @@ -1,12 +1,9 @@ #nullable enable -Microsoft.Maui.Graphics.Color.Color(Microsoft.Maui.Graphics.Color! original) -> void override Microsoft.Maui.Graphics.Color.Equals(object? obj) -> bool static Microsoft.Maui.Graphics.Color.operator !=(Microsoft.Maui.Graphics.Color? left, Microsoft.Maui.Graphics.Color? right) -> bool static Microsoft.Maui.Graphics.Color.operator ==(Microsoft.Maui.Graphics.Color? left, Microsoft.Maui.Graphics.Color? right) -> bool -virtual Microsoft.Maui.Graphics.Color.$() -> Microsoft.Maui.Graphics.Color! -virtual Microsoft.Maui.Graphics.Color.EqualityContract.get -> System.Type! -virtual Microsoft.Maui.Graphics.Color.PrintMembers(System.Text.StringBuilder! builder) -> bool -virtual Microsoft.Maui.Graphics.Color.Equals(Microsoft.Maui.Graphics.Color? other) -> bool +Microsoft.Maui.Graphics.Color.$() -> Microsoft.Maui.Graphics.Color! +Microsoft.Maui.Graphics.Color.Equals(Microsoft.Maui.Graphics.Color? other) -> bool Microsoft.Maui.Graphics.Color.AddLuminosity(float delta) -> Microsoft.Maui.Graphics.Color! Microsoft.Maui.Graphics.Color.GetComplementary() -> Microsoft.Maui.Graphics.Color! Microsoft.Maui.Graphics.Color.ToArgbHex(bool includeAlpha = false) -> string! diff --git a/src/Graphics/src/Graphics/PublicAPI/net/PublicAPI.Unshipped.txt b/src/Graphics/src/Graphics/PublicAPI/net/PublicAPI.Unshipped.txt index b40576003686..15dd3ad7ed64 100644 --- a/src/Graphics/src/Graphics/PublicAPI/net/PublicAPI.Unshipped.txt +++ b/src/Graphics/src/Graphics/PublicAPI/net/PublicAPI.Unshipped.txt @@ -1,12 +1,9 @@ #nullable enable -Microsoft.Maui.Graphics.Color.Color(Microsoft.Maui.Graphics.Color! original) -> void override Microsoft.Maui.Graphics.Color.Equals(object? obj) -> bool static Microsoft.Maui.Graphics.Color.operator !=(Microsoft.Maui.Graphics.Color? left, Microsoft.Maui.Graphics.Color? right) -> bool static Microsoft.Maui.Graphics.Color.operator ==(Microsoft.Maui.Graphics.Color? left, Microsoft.Maui.Graphics.Color? right) -> bool -virtual Microsoft.Maui.Graphics.Color.$() -> Microsoft.Maui.Graphics.Color! -virtual Microsoft.Maui.Graphics.Color.EqualityContract.get -> System.Type! -virtual Microsoft.Maui.Graphics.Color.Equals(Microsoft.Maui.Graphics.Color? other) -> bool -virtual Microsoft.Maui.Graphics.Color.PrintMembers(System.Text.StringBuilder! builder) -> bool +Microsoft.Maui.Graphics.Color.$() -> Microsoft.Maui.Graphics.Color! +Microsoft.Maui.Graphics.Color.Equals(Microsoft.Maui.Graphics.Color? other) -> bool Microsoft.Maui.Graphics.Color.AsPaint() -> Microsoft.Maui.Graphics.Paint! Microsoft.Maui.Graphics.Color.MultiplyAlpha(float multiplyBy) -> Microsoft.Maui.Graphics.Color! Microsoft.Maui.Graphics.Color.WithAlpha(float alpha) -> Microsoft.Maui.Graphics.Color! diff --git a/src/Graphics/src/Graphics/PublicAPI/netstandard/PublicAPI.Unshipped.txt b/src/Graphics/src/Graphics/PublicAPI/netstandard/PublicAPI.Unshipped.txt index b40576003686..15dd3ad7ed64 100644 --- a/src/Graphics/src/Graphics/PublicAPI/netstandard/PublicAPI.Unshipped.txt +++ b/src/Graphics/src/Graphics/PublicAPI/netstandard/PublicAPI.Unshipped.txt @@ -1,12 +1,9 @@ #nullable enable -Microsoft.Maui.Graphics.Color.Color(Microsoft.Maui.Graphics.Color! original) -> void override Microsoft.Maui.Graphics.Color.Equals(object? obj) -> bool static Microsoft.Maui.Graphics.Color.operator !=(Microsoft.Maui.Graphics.Color? left, Microsoft.Maui.Graphics.Color? right) -> bool static Microsoft.Maui.Graphics.Color.operator ==(Microsoft.Maui.Graphics.Color? left, Microsoft.Maui.Graphics.Color? right) -> bool -virtual Microsoft.Maui.Graphics.Color.$() -> Microsoft.Maui.Graphics.Color! -virtual Microsoft.Maui.Graphics.Color.EqualityContract.get -> System.Type! -virtual Microsoft.Maui.Graphics.Color.Equals(Microsoft.Maui.Graphics.Color? other) -> bool -virtual Microsoft.Maui.Graphics.Color.PrintMembers(System.Text.StringBuilder! builder) -> bool +Microsoft.Maui.Graphics.Color.$() -> Microsoft.Maui.Graphics.Color! +Microsoft.Maui.Graphics.Color.Equals(Microsoft.Maui.Graphics.Color? other) -> bool Microsoft.Maui.Graphics.Color.AsPaint() -> Microsoft.Maui.Graphics.Paint! Microsoft.Maui.Graphics.Color.MultiplyAlpha(float multiplyBy) -> Microsoft.Maui.Graphics.Color! Microsoft.Maui.Graphics.Color.WithAlpha(float alpha) -> Microsoft.Maui.Graphics.Color! diff --git a/src/Graphics/tests/Graphics.Tests/ColorUnitTests.cs b/src/Graphics/tests/Graphics.Tests/ColorUnitTests.cs index edaba8d32657..8dfd26efaa1e 100644 --- a/src/Graphics/tests/Graphics.Tests/ColorUnitTests.cs +++ b/src/Graphics/tests/Graphics.Tests/ColorUnitTests.cs @@ -468,5 +468,37 @@ public void TestParseAllBuiltInColors() Assert.Equal(expected, actual); } } + + [Fact] + public void ColorTypeIsSealed() + { + // Sealing Color guarantees every instance shares the same runtime type, so its + // record-generated equality (based on the ARGB value) can never be broken by a subclass. + Assert.True(typeof(Color).IsSealed); + } + + [Fact] + public void EqualsIsValueBasedForSameArgbValue() + { + var color1 = new Color(1f, 0f, 0f, 1f); + var color2 = new Color(1f, 0f, 0f, 1f); + + Assert.Equal(color1, color2); + Assert.True(color1 == color2); + Assert.True(color1.Equals(color2)); + Assert.True(EqualityComparer.Default.Equals(color1, color2)); + Assert.Equal(color1.GetHashCode(), color2.GetHashCode()); + } + + [Fact] + public void EqualsIsFalseForDifferentArgbValue() + { + var color1 = new Color(1f, 0f, 0f, 1f); + var color2 = new Color(0f, 1f, 0f, 1f); + + Assert.NotEqual(color1, color2); + Assert.True(color1 != color2); + Assert.False(color1.Equals(color2)); + } } }