Skip to content

Fix Color equality regression for derived types by sealing the record - #36443

Draft
Shalini-Ashokan wants to merge 2 commits into
dotnet:net11.0from
Shalini-Ashokan:fix-36034
Draft

Fix Color equality regression for derived types by sealing the record#36443
Shalini-Ashokan wants to merge 2 commits into
dotnet:net11.0from
Shalini-Ashokan:fix-36034

Conversation

@Shalini-Ashokan

Copy link
Copy Markdown
Contributor

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Issue Details

Color.Equals() returns false when comparing a base Color and a subclassed Color with identical RGBA values, even though ToInt() matches. Regression starting .NET MAUI 11 preview 3.

Root Cause

Color was converted from a class to a record class . Records auto-generate an EqualityContract check in Equals that requires both objects to have the exact same runtime type — so a base Color and a derived DerivedColor never match, even with identical byte values.

Description of Change

Made Color a sealed record class , so it can never be subclassed — every instance now shares the same EqualityContract , restoring pure value-based (ARGB) equality. Also removed the now-illegal virtual modifier on Equals(Color? other) since sealed types can't declare virtual members.

Issues Fixed

Fixes #36034

Reference :

#36076

#36076 (comment)

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 36443

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 36443"

@dotnet-policy-service dotnet-policy-service Bot added the community ✨ Community Contribution label Jul 8, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Hey there @@Shalini-Ashokan! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@dotnet-policy-service dotnet-policy-service Bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Jul 8, 2026
@kubaflo kubaflo added area-ai-agents Copilot CLI agents, agent skills, AI-assisted development and removed area-ai-agents Copilot CLI agents, agent skills, AI-assisted development labels Jul 8, 2026
@kubaflo

This comment has been minimized.

@github-actions github-actions Bot added the s/agent-review-in-progress AI review is currently running for this PR label Jul 8, 2026

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expert Review — 1 findings

See inline comments for details.

Comment thread src/Graphics/src/Graphics/Color.cs
@MauiBot MauiBot added s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Jul 8, 2026
MauiBot

This comment was marked as outdated.

@MauiBot MauiBot removed the s/agent-review-in-progress AI review is currently running for this PR label Jul 8, 2026
@kubaflo

This comment has been minimized.

@github-actions github-actions Bot added the s/agent-review-in-progress AI review is currently running for this PR label Jul 14, 2026
@MauiBot MauiBot added s/agent-fix-win AI found a better alternative fix than the PR and removed s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates labels Jul 14, 2026

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Review Summary

@Shalini-Ashokan — new AI review results are available based on this last commit: b4295f0. To request a fresh review after new comments or commits, comment /review rerun.

Gate Passed Confidence High Platform Android


🗂️ Review Sessions — click to expand
🚦 Gate — Test Before & After Fix

Gate Result: ✅ PASSED

Platform: ANDROID · Base: net11.0 · Merge base: 7f139ed4

Test Without Fix (expect FAIL) With Fix (expect PASS)
🧪 ColorUnitTests ColorUnitTests ✅ FAIL — 26s ✅ PASS — 18s
🔴 Without fix — 🧪 ColorUnitTests: FAIL ✅ · 26s
  Determining projects to restore...
  Restored /home/vsts/work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 1.65 sec).
  Restored /home/vsts/work/1/s/src/Graphics/src/Text.Markdig/Graphics.Text.Markdig.csproj (in 1.14 sec).
  Restored /home/vsts/work/1/s/src/Graphics/tests/Graphics.Tests/Graphics.Tests.csproj (in 2.92 sec).
  Restored /home/vsts/work/1/s/src/Graphics/samples/GraphicsTester.Portable/GraphicsTester.Portable.csproj (in 14 ms).
  Restored /home/vsts/work/1/s/src/Graphics/src/Graphics.Skia/Graphics.Skia.csproj (in 717 ms).
  ##vso[build.updatebuildnumber]11.0.0-ci+azdo.14657449
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net11.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]11.0.0-ci+azdo.14657449
  Graphics.Skia -> /home/vsts/work/1/s/artifacts/bin/Graphics.Skia/Debug/net11.0/Microsoft.Maui.Graphics.Skia.dll
  ##vso[build.updatebuildnumber]11.0.0-ci+azdo.14657449
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/netstandard2.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]11.0.0-ci+azdo.14657449
  Graphics.Text.Markdig -> /home/vsts/work/1/s/artifacts/bin/Graphics.Text.Markdig/Debug/netstandard2.0/Microsoft.Maui.Graphics.Text.Markdig.dll
  GraphicsTester.Portable -> /home/vsts/work/1/s/artifacts/bin/GraphicsTester.Portable/Debug/net11.0/GraphicsTester.Portable.dll
  Graphics.Tests -> /home/vsts/work/1/s/artifacts/bin/Graphics.Tests/Debug/net11.0/Graphics.Tests.dll
Test run for /home/vsts/work/1/s/artifacts/bin/Graphics.Tests/Debug/net11.0/Graphics.Tests.dll (.NETCoreApp,Version=v11.0)
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.01] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 11.0.0-preview.6.26325.125)
[xUnit.net 00:00:00.20]   Discovering: Graphics.Tests
[xUnit.net 00:00:00.50]   Discovered:  Graphics.Tests
[xUnit.net 00:00:00.52]   Starting:    Graphics.Tests
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "") [47 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "hsv(120, 100#, 50#)") [3 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "#12g") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: null) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "#ZZZ") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "hsv(120%, 100%, 50%)") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "hsva(120, 120%, 50%, a)") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "#1g3") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "#zyxv") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "222") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "notAColor") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "default") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "rgb255,0,0") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "rgb)255,0,0(") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "rgba(255, 0, 0, 0.8") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromHsvaDouble [5 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestSetHue [5 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHashCode [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestColorFromValue [12 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.GetComplementary(original: "#00FF00", expected: "#FF00FF") [6 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.GetComplementary(original: "#0000FF", expected: "#FFFF00") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.GetComplementary(original: "#0AF56C", expected: "#F50A93") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.GetComplementary(original: "#FF0000", expected: "#00FFFF") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHSLModifiers [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestToString [4 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromHex [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHSLToRGB [2 ms]
[xUnit.net 00:00:00.90]       Assert.True() Failure
[xUnit.net 00:00:00.90]       Expected: True
[xUnit.net 00:00:00.90]       Actual:   False
[xUnit.net 00:00:00.90]       Stack Trace:
[xUnit.net 00:00:00.90]         /_/src/Graphics/tests/Graphics.Tests/ColorUnitTests.cs(477,0): at Microsoft.Maui.Graphics.Tests.ColorUnitTests.ColorTypeIsSealed()
[xUnit.net 00:00:00.90]            at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
[xUnit.net 00:00:00.90]            at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestAddLuminosity [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHashCodeNamedColors [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.ToUInt [8 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.DefaultColorsMatch [< 1 ms]
  Failed Microsoft.Maui.Graphics.Tests.ColorUnitTests.ColorTypeIsSealed [2 ms]
  Error Message:
   Assert.True() Failure
Expected: True
Actual:   False
  Stack Trace:
     at Microsoft.Maui.Graphics.Tests.ColorUnitTests.ColorTypeIsSealed() in /_/src/Graphics/tests/Graphics.Tests/ColorUnitTests.cs:line 477
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromUint [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestRGBToHSL [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseAllBuiltInColors [3 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestToHex [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHSLPostSetEquality [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#111", expected: [Color: Red=0.06666667, Green=0.06666667, Blue=0.06666667, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#a222", expected: [Color: Red=0.13333334, Green=0.13333334, Blue=0.13333334, Alpha=0.6666667]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#C2F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=0.7607843]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#000000", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#000", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#00FFff 40%", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "111", expected: [Color: Red=0.06666667, Green=0.06666667, Blue=0.06666667, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "a222", expected: [Color: Red=0.13333334, Green=0.13333334, Blue=0.13333334, Alpha=0.6666667]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "C2F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=0.7607843]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "#111", expected: [Color: Red=0.06666667, Green=0.06666667, Blue=0.06666667, Alpha=1]) [3 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "#a222", expected: [Color: Red=0.6666667, Green=0.13333334, Blue=0.13333334, Alpha=0.13333334]) [1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "#F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "#C2F2E2D2", expected: [Color: Red=0.7607843, Green=0.9490196, Blue=0.8862745, Alpha=0.8235294]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "111", expected: [Color: Red=0.06666667, Green=0.06666667, Blue=0.06666667, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "a222", expected: [Color: Red=0.6666667, Green=0.13333334, Blue=0.13333334, Alpha=0.13333334]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "C2F2E2D2", expected: [Color: Red=0.7607843, Green=0.9490196, Blue=0.8862745, Alpha=0.8235294]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#111", expected: [Color: Red=0.06666667, Green=0.06666667, Blue=0.06666667, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#a222", expected: [Color: Red=0.13333334, Green=0.13333334, Blue=0.13333334, Alpha=0.6666667]) [2 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#C2F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=0.7607843]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#000000", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#000", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#00FFff 40%", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "rgb(255,0,0)", expected: [Color: Red=1, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "rgb(100%, 0%, 0%)", expected: [Color: Red=1, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "rgba(0, 255, 0, 0.7)", expected: [Color: Red=0, Green=1, Blue=0, Alpha=0.7]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "rgba(0%, 100%, 0%, 0.7)", expected: [Color: Red=0, Green=1, Blue=0, Alpha=0.7]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsl(120, 100%, 50%)", expected: [Color: Red=0, Green=1, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsl(120, 75, 20%)", expected: [Color: Red=0.050000012, Green=0.35, Blue=0.050000012, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsla(160, 100%, 50%, .4)", expected: [Color: Red=0, Green=1, Blue=0.6666666, Alpha=0.4]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsla(160,100%,50%,.6)", expected: [Color: Red=0, Green=1, Blue=0.6666666, Alpha=0.6]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsv(120, 85%, 35%)", expected: [Color: Red=0.05249999, Green=0.35, Blue=0.05249999, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsv(120, 85, 35)", expected: [Color: Red=0.05249999, Green=0.35, Blue=0.05249999, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsva(120, 100%, 50%, .8)", expected: [Color: Red=0, Green=0.5, Blue=0, Alpha=0.8]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsva(120, 100, 50, .8)", expected: [Color: Red=0, Green=0.5, Blue=0, Alpha=0.8]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestZeroLuminosity [9 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.EqualsIsValueBasedForSameArgbValue [13 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromHsv [6 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestClamping [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.EqualsIsFalseForDifferentArgbValue [8 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHashCodeAll [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.ZeroLuminToRGB [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromHsva [7 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromHsvDouble [< 1 ms]
[xUnit.net 00:00:00.90]     Microsoft.Maui.Graphics.Tests.ColorUnitTests.ColorTypeIsSealed [FAIL]
[xUnit.net 00:00:00.97]   Finished:    Graphics.Tests
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.FromRGBADouble [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestMultiplyAlpha [12 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.FromRGBDouble [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHSLPostSetInequality [2 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHSLSetToDefaultValue [< 1 ms]

Test Run Failed.
Total tests: 89
     Passed: 88
     Failed: 1
 Total time: 2.7170 Seconds

🟢 With fix — 🧪 ColorUnitTests: PASS ✅ · 18s
  Determining projects to restore...
  All projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]11.0.0-ci+azdo.14657449
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net11.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]11.0.0-ci+azdo.14657449
  ##vso[build.updatebuildnumber]11.0.0-ci+azdo.14657449
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/netstandard2.0/Microsoft.Maui.Graphics.dll
  Graphics.Skia -> /home/vsts/work/1/s/artifacts/bin/Graphics.Skia/Debug/net11.0/Microsoft.Maui.Graphics.Skia.dll
  ##vso[build.updatebuildnumber]11.0.0-ci+azdo.14657449
  Graphics.Text.Markdig -> /home/vsts/work/1/s/artifacts/bin/Graphics.Text.Markdig/Debug/netstandard2.0/Microsoft.Maui.Graphics.Text.Markdig.dll
  GraphicsTester.Portable -> /home/vsts/work/1/s/artifacts/bin/GraphicsTester.Portable/Debug/net11.0/GraphicsTester.Portable.dll
  Graphics.Tests -> /home/vsts/work/1/s/artifacts/bin/Graphics.Tests/Debug/net11.0/Graphics.Tests.dll
Test run for /home/vsts/work/1/s/artifacts/bin/Graphics.Tests/Debug/net11.0/Graphics.Tests.dll (.NETCoreApp,Version=v11.0)
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.01] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 11.0.0-preview.6.26325.125)
[xUnit.net 00:00:00.33]   Discovering: Graphics.Tests
[xUnit.net 00:00:00.67]   Discovered:  Graphics.Tests
[xUnit.net 00:00:00.71]   Starting:    Graphics.Tests
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "") [39 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "hsv(120, 100#, 50#)") [5 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "#12g") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: null) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "#ZZZ") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "hsv(120%, 100%, 50%)") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "hsva(120, 120%, 50%, a)") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "#1g3") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "#zyxv") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "222") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "notAColor") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "default") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "rgb255,0,0") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "rgb)255,0,0(") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "rgba(255, 0, 0, 0.8") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromHsvaDouble [1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestSetHue [5 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHashCode [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestColorFromValue [16 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.GetComplementary(original: "#00FF00", expected: "#FF00FF") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.GetComplementary(original: "#0000FF", expected: "#FFFF00") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.GetComplementary(original: "#0AF56C", expected: "#F50A93") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.GetComplementary(original: "#FF0000", expected: "#00FFFF") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHSLModifiers [3 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestToString [2 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromHex [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHSLToRGB [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestAddLuminosity [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHashCodeNamedColors [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.ToUInt [10 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.DefaultColorsMatch [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.ColorTypeIsSealed [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromUint [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestRGBToHSL [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseAllBuiltInColors [5 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestToHex [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHSLPostSetEquality [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#111", expected: [Color: Red=0.06666667, Green=0.06666667, Blue=0.06666667, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#a222", expected: [Color: Red=0.13333334, Green=0.13333334, Blue=0.13333334, Alpha=0.6666667]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#C2F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=0.7607843]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#000000", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#000", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#00FFff 40%", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "111", expected: [Color: Red=0.06666667, Green=0.06666667, Blue=0.06666667, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "a222", expected: [Color: Red=0.13333334, Green=0.13333334, Blue=0.13333334, Alpha=0.6666667]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "C2F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=0.7607843]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "#111", expected: [Color: Red=0.06666667, Green=0.06666667, Blue=0.06666667, Alpha=1]) [2 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "#a222", expected: [Color: Red=0.6666667, Green=0.13333334, Blue=0.13333334, Alpha=0.13333334]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "#F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "#C2F2E2D2", expected: [Color: Red=0.7607843, Green=0.9490196, Blue=0.8862745, Alpha=0.8235294]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "111", expected: [Color: Red=0.06666667, Green=0.06666667, Blue=0.06666667, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "a222", expected: [Color: Red=0.6666667, Green=0.13333334, Blue=0.13333334, Alpha=0.13333334]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "C2F2E2D2", expected: [Color: Red=0.7607843, Green=0.9490196, Blue=0.8862745, Alpha=0.8235294]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#111", expected: [Color: Red=0.06666667, Green=0.06666667, Blue=0.06666667, Alpha=1]) [4 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#a222", expected: [Color: Red=0.13333334, Green=0.13333334, Blue=0.13333334, Alpha=0.6666667]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#C2F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=0.7607843]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#000000", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#000", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#00FFff 40%", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "rgb(255,0,0)", expected: [Color: Red=1, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "rgb(100%, 0%, 0%)", expected: [Color: Red=1, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "rgba(0, 255, 0, 0.7)", expected: [Color: Red=0, Green=1, Blue=0, Alpha=0.7]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "rgba(0%, 100%, 0%, 0.7)", expected: [Color: Red=0, Green=1, Blue=0, Alpha=0.7]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsl(120, 100%, 50%)", expected: [Color: Red=0, Green=1, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsl(120, 75, 20%)", expected: [Color: Red=0.050000012, Green=0.35, Blue=0.050000012, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsla(160, 100%, 50%, .4)", expected: [Color: Red=0, Green=1, Blue=0.6666666, Alpha=0.4]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsla(160,100%,50%,.6)", expected: [Color: Red=0, Green=1, Blue=0.6666666, Alpha=0.6]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsv(120, 85%, 35%)", expected: [Color: Red=0.05249999, Green=0.35, Blue=0.05249999, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsv(120, 85, 35)", expected: [Color: Red=0.05249999, Green=0.35, Blue=0.05249999, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsva(120, 100%, 50%, .8)", expected: [Color: Red=0, Green=0.5, Blue=0, Alpha=0.8]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsva(120, 100, 50, .8)", expected: [Color: Red=0, Green=0.5, Blue=0, Alpha=0.8]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestZeroLuminosity [9 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.EqualsIsValueBasedForSameArgbValue [10 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromHsv [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestClamping [4 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.EqualsIsFalseForDifferentArgbValue [6 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHashCodeAll [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.ZeroLuminToRGB [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromHsva [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromHsvDouble [< 1 ms]
[xUnit.net 00:00:01.15]   Finished:    Graphics.Tests
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.FromRGBADouble [3 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestMultiplyAlpha [8 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.FromRGBDouble [2 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHSLPostSetInequality [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHSLSetToDefaultValue [< 1 ms]

Test Run Successful.
Total tests: 89
     Passed: 89
 Total time: 2.6078 Seconds

📁 Fix files reverted (9 files)
  • src/Graphics/src/Graphics/Color.cs
  • src/Graphics/src/Graphics/PublicAPI/net-android/PublicAPI.Unshipped.txt
  • src/Graphics/src/Graphics/PublicAPI/net-ios/PublicAPI.Unshipped.txt
  • src/Graphics/src/Graphics/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt
  • src/Graphics/src/Graphics/PublicAPI/net-macos/PublicAPI.Unshipped.txt
  • src/Graphics/src/Graphics/PublicAPI/net-tizen/PublicAPI.Unshipped.txt
  • src/Graphics/src/Graphics/PublicAPI/net-windows/PublicAPI.Unshipped.txt
  • src/Graphics/src/Graphics/PublicAPI/net/PublicAPI.Unshipped.txt
  • src/Graphics/src/Graphics/PublicAPI/netstandard/PublicAPI.Unshipped.txt

📋 Pre-Flight — Context & Validation

Issue: #36034 - Color record conversion changes equality for derived Color types
PR: #36443 - [WIP] Fix Color equality regression for derived types by sealing the record
Platforms Affected: Android, iOS, Windows, macOS, Tizen/Linux/other via shared Microsoft.Maui.Graphics
Files Changed: 9 implementation/API, 1 test

Key Findings

  • #36034 is a regression from .NET MAUI 11 preview 3: Color became a record class, so record equality requires matching EqualityContract and returns false for base-vs-derived colors with identical ARGB values.
  • PR #36443 fixes the symptom by sealing Color, but that removes subclassing and was already flagged by MauiBot as a public source/binary breaking change.
  • The gate result provided by the caller passed: tests fail without the PR fix and pass with it. Gate verification was not rerun.
  • Relevant test type is unit test: src/Graphics/tests/Graphics.Tests/Graphics.Tests.csproj --filter ColorUnitTests.

Code Review Summary

Verdict: NEEDS_CHANGES
Confidence: high
Errors: 1 | Warnings: 1 | Suggestions: 0

Key code review findings:

  • src/Graphics/src/Graphics/Color.cs:22 seals public Color, breaking existing source/binary consumers that derive from it.
  • src/Graphics/tests/Graphics.Tests/ColorUnitTests.cs:472 tests sealing rather than the original base-vs-derived equality regression.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #36443 Seal Color so record equality cannot compare different runtime types. ✅ PASSED (Gate) Color.cs, PublicAPI files, ColorUnitTests.cs Original PR; fixes symptom with breaking inheritance change.

🔬 Code Review — Deep Analysis

Code Review — PR #36443

Independent Assessment

What this changes: The PR changes Microsoft.Maui.Graphics.Color from public record class to public sealed record class, removes virtual from Equals(Color?), updates record-generated PublicAPI entries, and adds tests proving Color is sealed plus same-type value equality.

Inferred motivation: The change attempts to avoid record EqualityContract mismatches by making all Color instances share the same runtime type.

Reconciliation with PR Narrative

Author claims: PR #36443 fixes #36034, where Color record conversion caused base Color and derived Color instances with the same ARGB value to compare unequal.

Agreement/disagreement: The root cause is correct: record equality introduced runtime-type checks. The implementation avoids the scenario by prohibiting subclassing rather than restoring compatible subclass equality.

Prior Review Reconciliation

Prior ❌ Error Finding Source Status Evidence
Sealing shipped public Color is a source/binary breaking change for apps/libraries deriving from Color. MauiBot inline review ❌ Unresolved src/Graphics/src/Graphics/Color.cs:22 changes public record class Color to public sealed record class Color.

Blast Radius Assessment

  • Runs for all instances: Yes. The type declaration changes globally for Microsoft.Maui.Graphics.Color.
  • Startup impact: No direct startup work is introduced.
  • Static/shared state: None.
  • Public API impact: High. The change removes the ability to derive from Color and changes record-generated API shape.

CI Status

  • Required-check result: undetermined; gh was unavailable because authentication was not configured in this environment.
  • Classification: undetermined.
  • Action taken: confidence capped for CI status. The supplied gate result for the relevant regression tests was already passed and was not rerun.

Findings

❌ Error — Sealing Color is a public API breaking change

src/Graphics/src/Graphics/Color.cs:22 changes Color to sealed. Existing source with class BrandColor : Color no longer compiles, and existing binaries with derived Color types can fail to load. This fixes the equality symptom by removing the original supported scenario.

⚠️ Warning — Regression test locks in the breaking behavior

src/Graphics/tests/Graphics.Tests/ColorUnitTests.cs:472 asserts typeof(Color).IsSealed, but #36034 is specifically about base-vs-derived Color equality. The test no longer exercises the reported compatibility regression.

Failure-Mode Probing

  • Existing source subclass: fails to compile because Color is sealed.
  • Existing binary subclass: can fail to load against the new assembly.
  • Original reproduction: can no longer be represented because deriving from Color is prohibited.
  • Same-type equality: still passes, but that is not the problematic scenario.

Verdict: NEEDS_CHANGES

Confidence: high for the API compatibility issue; low for CI status because required checks could not be queried.
Summary: The PR identifies the right root cause but fixes it with a breaking public API change. Alternative candidates should preserve Color subclassing or explicitly justify a breaking change.


🛠️ Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix-1 Keep Color as an unsealed record and remove the EqualityContract check from Equals(Color?). ❌ FAIL 2 files Runtime equality still used record-generated Equals(object?); overriding it caused CS0111.
2 try-fix-2 Convert Color to an explicit class : IEquatable<Color> with ARGB equality/operators and remove record-only unshipped API. ✅ PASS 10 files Preserves subclassing and passes ColorUnitTests; expert review found no blockers.
PR PR #36443 Seal Color so record equality cannot compare different runtime types. ✅ PASSED (Gate) 10 files Fixes symptom but breaks public inheritance compatibility.

Cross-Pollination

Model Round New Ideas? Details
maui-expert-reviewer 1 Yes Suggested avoiding sealing by either removing record equality semantics or reverting away from record class.
maui-expert-reviewer 2 No Reviewed candidate 2 and found no blocking issues; caveat is only preview/unshipped record API compatibility.

Exhausted: No
Selected Fix: Candidate #2 — It passes the regression tests and is demonstrably better than PR #36443 because it fixes the equality regression without sealing the public Color type.


📝 Recommended PR Title & Description

Assessment: ✏️ Recommend updating — the winning fix is try-fix-2, not the current sealing approach, so the current title and description are now stale and describe the rejected implementation.

Recommended title

Graphics: Restore Color value equality without sealing the type

Recommended description

### Issue Details
`Color.Equals()` returns `false` when comparing a base `Color` and a subclassed `Color` with identical RGBA values, even though `ToInt()` matches. This is a regression starting in .NET MAUI 11 preview 3.

### Root Cause
`Color` was converted from a `class` to a `record class`. Records auto-generate equality paths that include an `EqualityContract` runtime-type check, so a base `Color` and a derived `Color` do not compare equal even when their byte-precision ARGB values match.

### Description of Change
Converted `Color` back to an explicit `class : IEquatable<Color>` and implemented value equality directly:

- `Equals(Color?)` compares the byte-precision ARGB value via `ToInt()`.
- `Equals(object?)`, `==`, and `!=` route through the same `Color` value equality.
- Record-generated members such as `EqualityContract`, `<Clone>$`, and `PrintMembers` are removed from `PublicAPI.Unshipped.txt`.
- Regression coverage now compares a base `Color` with a derived `Color` that has the same ARGB value.

This preserves the shipped ability to subclass `Color` while restoring value-based equality.

### What NOT to Do
- Do not seal `Color` just to avoid record equality's `EqualityContract` check; that fixes the symptom but breaks public subclassing compatibility.
- Do not try to customize only `Equals(Color?)` while keeping `Color` as a record; record-generated equality paths still control other comparisons and `Equals(object?)` cannot be redefined cleanly.

### Issues Fixed
Fixes #36034

### Reference
https://github.com/dotnet/maui/pull/36076

https://github.com/dotnet/maui/pull/36076#issuecomment-4782959118

🏁 Report — Final Recommendation

Comparative Fix Report — PR #36443

Candidate ranking

Rank Candidate Regression tests Assessment
1 try-fix-2 ✅ PASS Best concrete fix. Restores value equality for base/derived Color instances without sealing the public Color type, updates PublicAPI to remove record-only unshipped members, and adds regression coverage for the original derived-color scenario.
2 pr-plus-reviewer ✅ PASS (same approach as try-fix-2) Applies expert reviewer feedback to the PR by replacing the sealing workaround with explicit class equality. Equivalent to try-fix-2, but try-fix-2 is the preserved concrete candidate diff from STEP 5a.
3 pr ✅ PASS Fixes the symptom by preventing subclasses, but introduces a public source/binary compatibility break by sealing Microsoft.Maui.Graphics.Color and tests the workaround rather than the original regression.
4 try-fix-1 ❌ FAIL Attempted to keep Color as an unsealed record and remove EqualityContract from Equals(Color?), but record-generated equality paths still failed and adding Equals(object?) caused CS0111. Failed regression/build validation, so it ranks below all passing candidates.

CI and prior-review context

  • Required/public checks for the PR head showed maui-pr failed. Public AzDO log inspection found failures outside the Graphics/Color change area:
    • Microsoft.Maui.UnitTests.dll Helix work item failed in DispatcherTests.CreateTimerNonRepeatingDoesNotRepeat with NullReferenceException.
    • Build Windows (Debug) failed while importing/copying build-task files because files under .buildtasks were locked by .NET Host processes.
  • These failures do not directly implicate src/Graphics/src/Graphics/Color.cs or ColorUnitTests.
  • Prior MauiBot/expert review already flagged the same unresolved major issue: sealing shipped Color is a breaking public API change.

Winning candidate

Winner: try-fix-2

try-fix-2 is the single best candidate because it passes the regression tests and addresses the actual root cause without removing the shipped ability to derive from Color. It also improves test coverage by checking base-vs-derived equality directly, whereas the raw PR locks in sealing as the behavior.

Recommendation

Do not merge the raw PR fix as submitted. Replace the PR implementation with try-fix-2/pr-plus-reviewer: make Color an explicit class : IEquatable<Color>, implement value equality/operators directly, remove record-generated API surface from PublicAPI.Unshipped, and keep the derived-color regression test.


🧭 Next Steps — alternative fix proposed (try-fix-2)

Automated review — alternative fix proposed

The expert-reviewer evaluation compared the PR fix against automatically generated candidates and selected try-fix-2 as the strongest fix.

Why: try-fix-2 passes the regression tests and fixes Color value equality for derived types without sealing the public Color type. It avoids the PR fix public API break and includes direct derived-color regression coverage.

Please consider applying the candidate diff below (or use it as guidance). Once you push an update, this workflow will re-trigger and re-evaluate.

Candidate diff (try-fix-2)
diff --git a/src/Graphics/src/Graphics/Color.cs b/src/Graphics/src/Graphics/Color.cs
index 866d740377..a32125e976 100644
--- a/src/Graphics/src/Graphics/Color.cs
+++ b/src/Graphics/src/Graphics/Color.cs
@@ -14,7 +14,7 @@ namespace Microsoft.Maui.Graphics
 	[DebuggerDisplay("Red={Red}, Green={Green}, Blue={Blue}, Alpha={Alpha}")]
 	[TypeConverter(typeof(Converters.ColorTypeConverter))]
 	[ImmutableObject(true)]
-	public record class Color
+	public class Color : IEquatable<Color>
 	{
 		/// <summary>
 		/// The red component of the color, ranging from 0.0 to 1.0.
@@ -116,6 +116,21 @@ namespace Microsoft.Maui.Graphics
 
 		public override int GetHashCode() => ToInt();
 
+		public override bool Equals(object? obj) => obj is Color other && Equals(other);
+
+		public static bool operator ==(Color? left, Color? right)
+		{
+			if (ReferenceEquals(left, right))
+				return true;
+
+			if (left is null || right is null)
+				return false;
+
+			return left.Equals(right);
+		}
+
+		public static bool operator !=(Color? left, Color? right) => !(left == right);
+
 		/// <summary>
 		/// Determines whether the specified <see cref="Color"/> is equal to the current color using byte-precision comparison.
 		/// </summary>
@@ -124,9 +139,6 @@ namespace Microsoft.Maui.Graphics
 			if (other is null)
 				return false;
 
-			if (EqualityContract != other.EqualityContract)
-				return false;
-
 			return ToInt() == other.ToInt();
 		}
 
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 52af5b2eb3..9ff6b16efc 100644
--- a/src/Graphics/src/Graphics/PublicAPI/net-android/PublicAPI.Unshipped.txt
+++ b/src/Graphics/src/Graphics/PublicAPI/net-android/PublicAPI.Unshipped.txt
@@ -1,11 +1,7 @@
 #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.<Clone>$() -> 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.AddLuminosity(float delta) -> Microsoft.Maui.Graphics.Color!
 Microsoft.Maui.Graphics.Color.ToArgbHex(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 b405760036..bafe3bc313 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,8 @@
 #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.<Clone>$() -> 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.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 b405760036..bafe3bc313 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,8 @@
 #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.<Clone>$() -> 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.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 55c756b6c1..d9765177a1 100644
--- a/src/Graphics/src/Graphics/PublicAPI/net-macos/PublicAPI.Unshipped.txt
+++ b/src/Graphics/src/Graphics/PublicAPI/net-macos/PublicAPI.Unshipped.txt
@@ -1,11 +1,7 @@
 #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.<Clone>$() -> 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.AddLuminosity(float delta) -> Microsoft.Maui.Graphics.Color!
 Microsoft.Maui.Graphics.Color.GetComplementary() -> Microsoft.Maui.Graphics.Color!
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 55c756b6c1..d9765177a1 100644
--- a/src/Graphics/src/Graphics/PublicAPI/net-tizen/PublicAPI.Unshipped.txt
+++ b/src/Graphics/src/Graphics/PublicAPI/net-tizen/PublicAPI.Unshipped.txt
@@ -1,11 +1,7 @@
 #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.<Clone>$() -> 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.AddLuminosity(float delta) -> Microsoft.Maui.Graphics.Color!
 Microsoft.Maui.Graphics.Color.GetComplementary() -> Microsoft.Maui.Graphics.Color!
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 55c756b6c1..d9765177a1 100644
--- a/src/Graphics/src/Graphics/PublicAPI/net-windows/PublicAPI.Unshipped.txt
+++ b/src/Graphics/src/Graphics/PublicAPI/net-windows/PublicAPI.Unshipped.txt
@@ -1,11 +1,7 @@
 #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.<Clone>$() -> 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.AddLuminosity(float delta) -> Microsoft.Maui.Graphics.Color!
 Microsoft.Maui.Graphics.Color.GetComplementary() -> Microsoft.Maui.Graphics.Color!
diff --git a/src/Graphics/src/Graphics/PublicAPI/net/PublicAPI.Unshipped.txt b/src/Graphics/src/Graphics/PublicAPI/net/PublicAPI.Unshipped.txt
index b405760036..bafe3bc313 100644
--- a/src/Graphics/src/Graphics/PublicAPI/net/PublicAPI.Unshipped.txt
+++ b/src/Graphics/src/Graphics/PublicAPI/net/PublicAPI.Unshipped.txt
@@ -1,12 +1,8 @@
 #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.<Clone>$() -> 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.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 b405760036..bafe3bc313 100644
--- a/src/Graphics/src/Graphics/PublicAPI/netstandard/PublicAPI.Unshipped.txt
+++ b/src/Graphics/src/Graphics/PublicAPI/netstandard/PublicAPI.Unshipped.txt
@@ -1,12 +1,8 @@
 #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.<Clone>$() -> 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.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 8dfd26efaa..cc9225c80b 100644
--- a/src/Graphics/tests/Graphics.Tests/ColorUnitTests.cs
+++ b/src/Graphics/tests/Graphics.Tests/ColorUnitTests.cs
@@ -470,11 +470,20 @@ namespace Microsoft.Maui.Graphics.Tests
 		}
 
 		[Fact]
-		public void ColorTypeIsSealed()
+		public void EqualsIsValueBasedForDerivedColorWithSameArgbValue()
 		{
-			// 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);
+			var baseColor = new Color(1f, 0f, 0f, 1f);
+			Color derivedColor = new DerivedColor(1f, 0f, 0f, 1f);
+
+			Assert.Equal(baseColor.ToInt(), derivedColor.ToInt());
+			Assert.Equal(baseColor, derivedColor);
+			Assert.Equal(derivedColor, baseColor);
+			Assert.True(baseColor == derivedColor);
+			Assert.True(derivedColor == baseColor);
+			Assert.True(baseColor.Equals(derivedColor));
+			Assert.True(derivedColor.Equals(baseColor));
+			Assert.True(EqualityComparer<Color>.Default.Equals(baseColor, derivedColor));
+			Assert.Equal(baseColor.GetHashCode(), derivedColor.GetHashCode());
 		}
 
 		[Fact]
@@ -500,5 +509,13 @@ namespace Microsoft.Maui.Graphics.Tests
 			Assert.True(color1 != color2);
 			Assert.False(color1.Equals(color2));
 		}
+
+		sealed class DerivedColor : Color
+		{
+			public DerivedColor(float red, float green, float blue, float alpha)
+				: base(red, green, blue, alpha)
+			{
+			}
+		}
 	}
 }

@MauiBot MauiBot removed the s/agent-review-in-progress AI review is currently running for this PR label Jul 14, 2026
@Shalini-Ashokan Shalini-Ashokan changed the title [WIP] Fix Color equality regression for derived types by sealing the record Fix Color equality regression for derived types by sealing the record Jul 15, 2026

@kubaflo kubaflo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please check the ai's suggestions?

@Shalini-Ashokan

Copy link
Copy Markdown
Contributor Author

AI Review Summary

@Shalini-Ashokan — new AI review results are available based on this last commit: b4295f0. To request a fresh review after new comments or commits, comment /review rerun.

Gate Passed Confidence High Platform Android

🗂️ Review Sessions — click to expand

🚦 Gate — Test Before & After Fix

Gate Result: ✅ PASSED

Platform: ANDROID · Base: net11.0 · Merge base: 7f139ed4

Test Without Fix (expect FAIL) With Fix (expect PASS)
🧪 ColorUnitTests ColorUnitTests ✅ FAIL — 26s ✅ PASS — 18s
🔴 Without fix — 🧪 ColorUnitTests: FAIL ✅ · 26s

  Determining projects to restore...
  Restored /home/vsts/work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 1.65 sec).
  Restored /home/vsts/work/1/s/src/Graphics/src/Text.Markdig/Graphics.Text.Markdig.csproj (in 1.14 sec).
  Restored /home/vsts/work/1/s/src/Graphics/tests/Graphics.Tests/Graphics.Tests.csproj (in 2.92 sec).
  Restored /home/vsts/work/1/s/src/Graphics/samples/GraphicsTester.Portable/GraphicsTester.Portable.csproj (in 14 ms).
  Restored /home/vsts/work/1/s/src/Graphics/src/Graphics.Skia/Graphics.Skia.csproj (in 717 ms).
  ##vso[build.updatebuildnumber]11.0.0-ci+azdo.14657449
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net11.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]11.0.0-ci+azdo.14657449
  Graphics.Skia -> /home/vsts/work/1/s/artifacts/bin/Graphics.Skia/Debug/net11.0/Microsoft.Maui.Graphics.Skia.dll
  ##vso[build.updatebuildnumber]11.0.0-ci+azdo.14657449
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/netstandard2.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]11.0.0-ci+azdo.14657449
  Graphics.Text.Markdig -> /home/vsts/work/1/s/artifacts/bin/Graphics.Text.Markdig/Debug/netstandard2.0/Microsoft.Maui.Graphics.Text.Markdig.dll
  GraphicsTester.Portable -> /home/vsts/work/1/s/artifacts/bin/GraphicsTester.Portable/Debug/net11.0/GraphicsTester.Portable.dll
  Graphics.Tests -> /home/vsts/work/1/s/artifacts/bin/Graphics.Tests/Debug/net11.0/Graphics.Tests.dll
Test run for /home/vsts/work/1/s/artifacts/bin/Graphics.Tests/Debug/net11.0/Graphics.Tests.dll (.NETCoreApp,Version=v11.0)
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.01] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 11.0.0-preview.6.26325.125)
[xUnit.net 00:00:00.20]   Discovering: Graphics.Tests
[xUnit.net 00:00:00.50]   Discovered:  Graphics.Tests
[xUnit.net 00:00:00.52]   Starting:    Graphics.Tests
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "") [47 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "hsv(120, 100#, 50#)") [3 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "#12g") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: null) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "#ZZZ") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "hsv(120%, 100%, 50%)") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "hsva(120, 120%, 50%, a)") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "#1g3") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "#zyxv") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "222") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "notAColor") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "default") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "rgb255,0,0") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "rgb)255,0,0(") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "rgba(255, 0, 0, 0.8") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromHsvaDouble [5 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestSetHue [5 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHashCode [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestColorFromValue [12 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.GetComplementary(original: "#00FF00", expected: "#FF00FF") [6 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.GetComplementary(original: "#0000FF", expected: "#FFFF00") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.GetComplementary(original: "#0AF56C", expected: "#F50A93") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.GetComplementary(original: "#FF0000", expected: "#00FFFF") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHSLModifiers [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestToString [4 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromHex [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHSLToRGB [2 ms]
[xUnit.net 00:00:00.90]       Assert.True() Failure
[xUnit.net 00:00:00.90]       Expected: True
[xUnit.net 00:00:00.90]       Actual:   False
[xUnit.net 00:00:00.90]       Stack Trace:
[xUnit.net 00:00:00.90]         /_/src/Graphics/tests/Graphics.Tests/ColorUnitTests.cs(477,0): at Microsoft.Maui.Graphics.Tests.ColorUnitTests.ColorTypeIsSealed()
[xUnit.net 00:00:00.90]            at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
[xUnit.net 00:00:00.90]            at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestAddLuminosity [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHashCodeNamedColors [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.ToUInt [8 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.DefaultColorsMatch [< 1 ms]
  Failed Microsoft.Maui.Graphics.Tests.ColorUnitTests.ColorTypeIsSealed [2 ms]
  Error Message:
   Assert.True() Failure
Expected: True
Actual:   False
  Stack Trace:
     at Microsoft.Maui.Graphics.Tests.ColorUnitTests.ColorTypeIsSealed() in /_/src/Graphics/tests/Graphics.Tests/ColorUnitTests.cs:line 477
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromUint [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestRGBToHSL [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseAllBuiltInColors [3 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestToHex [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHSLPostSetEquality [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#111", expected: [Color: Red=0.06666667, Green=0.06666667, Blue=0.06666667, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#a222", expected: [Color: Red=0.13333334, Green=0.13333334, Blue=0.13333334, Alpha=0.6666667]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#C2F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=0.7607843]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#000000", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#000", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#00FFff 40%", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "111", expected: [Color: Red=0.06666667, Green=0.06666667, Blue=0.06666667, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "a222", expected: [Color: Red=0.13333334, Green=0.13333334, Blue=0.13333334, Alpha=0.6666667]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "C2F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=0.7607843]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "#111", expected: [Color: Red=0.06666667, Green=0.06666667, Blue=0.06666667, Alpha=1]) [3 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "#a222", expected: [Color: Red=0.6666667, Green=0.13333334, Blue=0.13333334, Alpha=0.13333334]) [1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "#F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "#C2F2E2D2", expected: [Color: Red=0.7607843, Green=0.9490196, Blue=0.8862745, Alpha=0.8235294]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "111", expected: [Color: Red=0.06666667, Green=0.06666667, Blue=0.06666667, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "a222", expected: [Color: Red=0.6666667, Green=0.13333334, Blue=0.13333334, Alpha=0.13333334]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "C2F2E2D2", expected: [Color: Red=0.7607843, Green=0.9490196, Blue=0.8862745, Alpha=0.8235294]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#111", expected: [Color: Red=0.06666667, Green=0.06666667, Blue=0.06666667, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#a222", expected: [Color: Red=0.13333334, Green=0.13333334, Blue=0.13333334, Alpha=0.6666667]) [2 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#C2F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=0.7607843]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#000000", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#000", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#00FFff 40%", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "rgb(255,0,0)", expected: [Color: Red=1, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "rgb(100%, 0%, 0%)", expected: [Color: Red=1, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "rgba(0, 255, 0, 0.7)", expected: [Color: Red=0, Green=1, Blue=0, Alpha=0.7]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "rgba(0%, 100%, 0%, 0.7)", expected: [Color: Red=0, Green=1, Blue=0, Alpha=0.7]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsl(120, 100%, 50%)", expected: [Color: Red=0, Green=1, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsl(120, 75, 20%)", expected: [Color: Red=0.050000012, Green=0.35, Blue=0.050000012, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsla(160, 100%, 50%, .4)", expected: [Color: Red=0, Green=1, Blue=0.6666666, Alpha=0.4]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsla(160,100%,50%,.6)", expected: [Color: Red=0, Green=1, Blue=0.6666666, Alpha=0.6]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsv(120, 85%, 35%)", expected: [Color: Red=0.05249999, Green=0.35, Blue=0.05249999, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsv(120, 85, 35)", expected: [Color: Red=0.05249999, Green=0.35, Blue=0.05249999, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsva(120, 100%, 50%, .8)", expected: [Color: Red=0, Green=0.5, Blue=0, Alpha=0.8]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsva(120, 100, 50, .8)", expected: [Color: Red=0, Green=0.5, Blue=0, Alpha=0.8]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestZeroLuminosity [9 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.EqualsIsValueBasedForSameArgbValue [13 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromHsv [6 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestClamping [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.EqualsIsFalseForDifferentArgbValue [8 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHashCodeAll [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.ZeroLuminToRGB [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromHsva [7 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromHsvDouble [< 1 ms]
[xUnit.net 00:00:00.90]     Microsoft.Maui.Graphics.Tests.ColorUnitTests.ColorTypeIsSealed [FAIL]
[xUnit.net 00:00:00.97]   Finished:    Graphics.Tests
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.FromRGBADouble [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestMultiplyAlpha [12 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.FromRGBDouble [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHSLPostSetInequality [2 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHSLSetToDefaultValue [< 1 ms]

Test Run Failed.
Total tests: 89
     Passed: 88
     Failed: 1
 Total time: 2.7170 Seconds

🟢 With fix — 🧪 ColorUnitTests: PASS ✅ · 18s

  Determining projects to restore...
  All projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]11.0.0-ci+azdo.14657449
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net11.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]11.0.0-ci+azdo.14657449
  ##vso[build.updatebuildnumber]11.0.0-ci+azdo.14657449
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/netstandard2.0/Microsoft.Maui.Graphics.dll
  Graphics.Skia -> /home/vsts/work/1/s/artifacts/bin/Graphics.Skia/Debug/net11.0/Microsoft.Maui.Graphics.Skia.dll
  ##vso[build.updatebuildnumber]11.0.0-ci+azdo.14657449
  Graphics.Text.Markdig -> /home/vsts/work/1/s/artifacts/bin/Graphics.Text.Markdig/Debug/netstandard2.0/Microsoft.Maui.Graphics.Text.Markdig.dll
  GraphicsTester.Portable -> /home/vsts/work/1/s/artifacts/bin/GraphicsTester.Portable/Debug/net11.0/GraphicsTester.Portable.dll
  Graphics.Tests -> /home/vsts/work/1/s/artifacts/bin/Graphics.Tests/Debug/net11.0/Graphics.Tests.dll
Test run for /home/vsts/work/1/s/artifacts/bin/Graphics.Tests/Debug/net11.0/Graphics.Tests.dll (.NETCoreApp,Version=v11.0)
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.01] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 11.0.0-preview.6.26325.125)
[xUnit.net 00:00:00.33]   Discovering: Graphics.Tests
[xUnit.net 00:00:00.67]   Discovered:  Graphics.Tests
[xUnit.net 00:00:00.71]   Starting:    Graphics.Tests
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "") [39 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "hsv(120, 100#, 50#)") [5 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "#12g") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: null) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "#ZZZ") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "hsv(120%, 100%, 50%)") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "hsva(120, 120%, 50%, a)") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "#1g3") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "#zyxv") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "222") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "notAColor") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "default") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "rgb255,0,0") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "rgb)255,0,0(") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseBad(badValue: "rgba(255, 0, 0, 0.8") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromHsvaDouble [1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestSetHue [5 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHashCode [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestColorFromValue [16 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.GetComplementary(original: "#00FF00", expected: "#FF00FF") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.GetComplementary(original: "#0000FF", expected: "#FFFF00") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.GetComplementary(original: "#0AF56C", expected: "#F50A93") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.GetComplementary(original: "#FF0000", expected: "#00FFFF") [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHSLModifiers [3 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestToString [2 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromHex [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHSLToRGB [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestAddLuminosity [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHashCodeNamedColors [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.ToUInt [10 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.DefaultColorsMatch [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.ColorTypeIsSealed [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromUint [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestRGBToHSL [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseAllBuiltInColors [5 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestToHex [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHSLPostSetEquality [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#111", expected: [Color: Red=0.06666667, Green=0.06666667, Blue=0.06666667, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#a222", expected: [Color: Red=0.13333334, Green=0.13333334, Blue=0.13333334, Alpha=0.6666667]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#C2F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=0.7607843]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#000000", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#000", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "#00FFff 40%", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "111", expected: [Color: Red=0.06666667, Green=0.06666667, Blue=0.06666667, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "a222", expected: [Color: Red=0.13333334, Green=0.13333334, Blue=0.13333334, Alpha=0.6666667]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromArgb(value: "C2F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=0.7607843]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "#111", expected: [Color: Red=0.06666667, Green=0.06666667, Blue=0.06666667, Alpha=1]) [2 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "#a222", expected: [Color: Red=0.6666667, Green=0.13333334, Blue=0.13333334, Alpha=0.13333334]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "#F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "#C2F2E2D2", expected: [Color: Red=0.7607843, Green=0.9490196, Blue=0.8862745, Alpha=0.8235294]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "111", expected: [Color: Red=0.06666667, Green=0.06666667, Blue=0.06666667, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "a222", expected: [Color: Red=0.6666667, Green=0.13333334, Blue=0.13333334, Alpha=0.13333334]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromRgba(value: "C2F2E2D2", expected: [Color: Red=0.7607843, Green=0.9490196, Blue=0.8862745, Alpha=0.8235294]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#111", expected: [Color: Red=0.06666667, Green=0.06666667, Blue=0.06666667, Alpha=1]) [4 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#a222", expected: [Color: Red=0.13333334, Green=0.13333334, Blue=0.13333334, Alpha=0.6666667]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#C2F2E2D2", expected: [Color: Red=0.9490196, Green=0.8862745, Blue=0.8235294, Alpha=0.7607843]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#000000", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#000", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "#00FFff 40%", expected: [Color: Red=0, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "rgb(255,0,0)", expected: [Color: Red=1, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "rgb(100%, 0%, 0%)", expected: [Color: Red=1, Green=0, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "rgba(0, 255, 0, 0.7)", expected: [Color: Red=0, Green=1, Blue=0, Alpha=0.7]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "rgba(0%, 100%, 0%, 0.7)", expected: [Color: Red=0, Green=1, Blue=0, Alpha=0.7]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsl(120, 100%, 50%)", expected: [Color: Red=0, Green=1, Blue=0, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsl(120, 75, 20%)", expected: [Color: Red=0.050000012, Green=0.35, Blue=0.050000012, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsla(160, 100%, 50%, .4)", expected: [Color: Red=0, Green=1, Blue=0.6666666, Alpha=0.4]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsla(160,100%,50%,.6)", expected: [Color: Red=0, Green=1, Blue=0.6666666, Alpha=0.6]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsv(120, 85%, 35%)", expected: [Color: Red=0.05249999, Green=0.35, Blue=0.05249999, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsv(120, 85, 35)", expected: [Color: Red=0.05249999, Green=0.35, Blue=0.05249999, Alpha=1]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsva(120, 100%, 50%, .8)", expected: [Color: Red=0, Green=0.5, Blue=0, Alpha=0.8]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestParseValid(value: "hsva(120, 100, 50, .8)", expected: [Color: Red=0, Green=0.5, Blue=0, Alpha=0.8]) [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestZeroLuminosity [9 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.EqualsIsValueBasedForSameArgbValue [10 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromHsv [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestClamping [4 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.EqualsIsFalseForDifferentArgbValue [6 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHashCodeAll [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.ZeroLuminToRGB [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromHsva [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestFromHsvDouble [< 1 ms]
[xUnit.net 00:00:01.15]   Finished:    Graphics.Tests
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.FromRGBADouble [3 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestMultiplyAlpha [8 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.FromRGBDouble [2 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHSLPostSetInequality [< 1 ms]
  Passed Microsoft.Maui.Graphics.Tests.ColorUnitTests.TestHSLSetToDefaultValue [< 1 ms]

Test Run Successful.
Total tests: 89
     Passed: 89
 Total time: 2.6078 Seconds

📁 Fix files reverted (9 files)

  • src/Graphics/src/Graphics/Color.cs
  • src/Graphics/src/Graphics/PublicAPI/net-android/PublicAPI.Unshipped.txt
  • src/Graphics/src/Graphics/PublicAPI/net-ios/PublicAPI.Unshipped.txt
  • src/Graphics/src/Graphics/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt
  • src/Graphics/src/Graphics/PublicAPI/net-macos/PublicAPI.Unshipped.txt
  • src/Graphics/src/Graphics/PublicAPI/net-tizen/PublicAPI.Unshipped.txt
  • src/Graphics/src/Graphics/PublicAPI/net-windows/PublicAPI.Unshipped.txt
  • src/Graphics/src/Graphics/PublicAPI/net/PublicAPI.Unshipped.txt
  • src/Graphics/src/Graphics/PublicAPI/netstandard/PublicAPI.Unshipped.txt

📋 Pre-Flight — Context & Validation

Issue: #36034 - Color record conversion changes equality for derived Color types PR: #36443 - [WIP] Fix Color equality regression for derived types by sealing the record Platforms Affected: Android, iOS, Windows, macOS, Tizen/Linux/other via shared Microsoft.Maui.Graphics Files Changed: 9 implementation/API, 1 test

Key Findings

Code Review Summary

Verdict: NEEDS_CHANGES Confidence: high Errors: 1 | Warnings: 1 | Suggestions: 0

Key code review findings:

  • src/Graphics/src/Graphics/Color.cs:22 seals public Color, breaking existing source/binary consumers that derive from it.
  • src/Graphics/tests/Graphics.Tests/ColorUnitTests.cs:472 tests sealing rather than the original base-vs-derived equality regression.

Fix Candidates

Source Approach Test Result Files Changed Notes

PR PR #36443 Seal Color so record equality cannot compare different runtime types. ✅ PASSED (Gate) Color.cs, PublicAPI files, ColorUnitTests.cs Original PR; fixes symptom with breaking inheritance change.
🔬 Code Review — Deep Analysis

Code Review — PR #36443

Independent Assessment

What this changes: The PR changes Microsoft.Maui.Graphics.Color from public record class to public sealed record class, removes virtual from Equals(Color?), updates record-generated PublicAPI entries, and adds tests proving Color is sealed plus same-type value equality.

Inferred motivation: The change attempts to avoid record EqualityContract mismatches by making all Color instances share the same runtime type.

Reconciliation with PR Narrative

Author claims: PR #36443 fixes #36034, where Color record conversion caused base Color and derived Color instances with the same ARGB value to compare unequal.

Agreement/disagreement: The root cause is correct: record equality introduced runtime-type checks. The implementation avoids the scenario by prohibiting subclassing rather than restoring compatible subclass equality.

Prior Review Reconciliation

Prior ❌ Error Finding Source Status Evidence
Sealing shipped public Color is a source/binary breaking change for apps/libraries deriving from Color. MauiBot inline review ❌ Unresolved src/Graphics/src/Graphics/Color.cs:22 changes public record class Color to public sealed record class Color.

Blast Radius Assessment

  • Runs for all instances: Yes. The type declaration changes globally for Microsoft.Maui.Graphics.Color.
  • Startup impact: No direct startup work is introduced.
  • Static/shared state: None.
  • Public API impact: High. The change removes the ability to derive from Color and changes record-generated API shape.

CI Status

  • Required-check result: undetermined; gh was unavailable because authentication was not configured in this environment.
  • Classification: undetermined.
  • Action taken: confidence capped for CI status. The supplied gate result for the relevant regression tests was already passed and was not rerun.

Findings

❌ Error — Sealing Color is a public API breaking change

src/Graphics/src/Graphics/Color.cs:22 changes Color to sealed. Existing source with class BrandColor : Color no longer compiles, and existing binaries with derived Color types can fail to load. This fixes the equality symptom by removing the original supported scenario.

⚠️ Warning — Regression test locks in the breaking behavior

src/Graphics/tests/Graphics.Tests/ColorUnitTests.cs:472 asserts typeof(Color).IsSealed, but #36034 is specifically about base-vs-derived Color equality. The test no longer exercises the reported compatibility regression.

Failure-Mode Probing

  • Existing source subclass: fails to compile because Color is sealed.
  • Existing binary subclass: can fail to load against the new assembly.
  • Original reproduction: can no longer be represented because deriving from Color is prohibited.
  • Same-type equality: still passes, but that is not the problematic scenario.

Verdict: NEEDS_CHANGES

Confidence: high for the API compatibility issue; low for CI status because required checks could not be queried. Summary: The PR identifies the right root cause but fixes it with a breaking public API change. Alternative candidates should preserve Color subclassing or explicitly justify a breaking change.

🛠️ Fix — Analysis & Comparison

Fix Candidates

Source Approach Test Result Files Changed Notes

1 try-fix-1 Keep Color as an unsealed record and remove the EqualityContract check from Equals(Color?). ❌ FAIL 2 files Runtime equality still used record-generated Equals(object?); overriding it caused CS0111.
2 try-fix-2 Convert Color to an explicit class : IEquatable<Color> with ARGB equality/operators and remove record-only unshipped API. ✅ PASS 10 files Preserves subclassing and passes ColorUnitTests; expert review found no blockers.
PR PR #36443 Seal Color so record equality cannot compare different runtime types. ✅ PASSED (Gate) 10 files Fixes symptom but breaks public inheritance compatibility.

Cross-Pollination

Model Round New Ideas? Details
maui-expert-reviewer 1 Yes Suggested avoiding sealing by either removing record equality semantics or reverting away from record class.
maui-expert-reviewer 2 No Reviewed candidate 2 and found no blocking issues; caveat is only preview/unshipped record API compatibility.
Exhausted: No Selected Fix: Candidate #2 — It passes the regression tests and is demonstrably better than PR #36443 because it fixes the equality regression without sealing the public Color type.

📝 Recommended PR Title & Description

Assessment: ✏️ Recommend updating — the winning fix is try-fix-2, not the current sealing approach, so the current title and description are now stale and describe the rejected implementation.

Recommended title

Graphics: Restore Color value equality without sealing the type

Recommended description

### Issue Details
`Color.Equals()` returns `false` when comparing a base `Color` and a subclassed `Color` with identical RGBA values, even though `ToInt()` matches. This is a regression starting in .NET MAUI 11 preview 3.

### Root Cause
`Color` was converted from a `class` to a `record class`. Records auto-generate equality paths that include an `EqualityContract` runtime-type check, so a base `Color` and a derived `Color` do not compare equal even when their byte-precision ARGB values match.

### Description of Change
Converted `Color` back to an explicit `class : IEquatable<Color>` and implemented value equality directly:

- `Equals(Color?)` compares the byte-precision ARGB value via `ToInt()`.
- `Equals(object?)`, `==`, and `!=` route through the same `Color` value equality.
- Record-generated members such as `EqualityContract`, `<Clone>$`, and `PrintMembers` are removed from `PublicAPI.Unshipped.txt`.
- Regression coverage now compares a base `Color` with a derived `Color` that has the same ARGB value.

This preserves the shipped ability to subclass `Color` while restoring value-based equality.

### What NOT to Do
- Do not seal `Color` just to avoid record equality's `EqualityContract` check; that fixes the symptom but breaks public subclassing compatibility.
- Do not try to customize only `Equals(Color?)` while keeping `Color` as a record; record-generated equality paths still control other comparisons and `Equals(object?)` cannot be redefined cleanly.

### Issues Fixed
Fixes #36034

### Reference
https://github.com/dotnet/maui/pull/36076

https://github.com/dotnet/maui/pull/36076#issuecomment-4782959118

🏁 Report — Final Recommendation

Comparative Fix Report — PR #36443

Candidate ranking

Rank Candidate Regression tests Assessment
1 try-fix-2 ✅ PASS Best concrete fix. Restores value equality for base/derived Color instances without sealing the public Color type, updates PublicAPI to remove record-only unshipped members, and adds regression coverage for the original derived-color scenario.
2 pr-plus-reviewer ✅ PASS (same approach as try-fix-2) Applies expert reviewer feedback to the PR by replacing the sealing workaround with explicit class equality. Equivalent to try-fix-2, but try-fix-2 is the preserved concrete candidate diff from STEP 5a.
3 pr ✅ PASS Fixes the symptom by preventing subclasses, but introduces a public source/binary compatibility break by sealing Microsoft.Maui.Graphics.Color and tests the workaround rather than the original regression.
4 try-fix-1 ❌ FAIL Attempted to keep Color as an unsealed record and remove EqualityContract from Equals(Color?), but record-generated equality paths still failed and adding Equals(object?) caused CS0111. Failed regression/build validation, so it ranks below all passing candidates.

CI and prior-review context

  • Required/public checks for the PR head showed maui-pr failed. Public AzDO log inspection found failures outside the Graphics/Color change area:

    • Microsoft.Maui.UnitTests.dll Helix work item failed in DispatcherTests.CreateTimerNonRepeatingDoesNotRepeat with NullReferenceException.
    • Build Windows (Debug) failed while importing/copying build-task files because files under .buildtasks were locked by .NET Host processes.
  • These failures do not directly implicate src/Graphics/src/Graphics/Color.cs or ColorUnitTests.

  • Prior MauiBot/expert review already flagged the same unresolved major issue: sealing shipped Color is a breaking public API change.

Winning candidate

Winner: try-fix-2

try-fix-2 is the single best candidate because it passes the regression tests and addresses the actual root cause without removing the shipped ability to derive from Color. It also improves test coverage by checking base-vs-derived equality directly, whereas the raw PR locks in sealing as the behavior.

Recommendation

Do not merge the raw PR fix as submitted. Replace the PR implementation with try-fix-2/pr-plus-reviewer: make Color an explicit class : IEquatable<Color>, implement value equality/operators directly, remove record-generated API surface from PublicAPI.Unshipped, and keep the derived-color regression test.

🧭 Next Steps — alternative fix proposed (try-fix-2)

This is intentional — we sealed Color on purpose, based on @AdamEssenmacher's suggestion in the issue. It fixes the equality bug, but means anyone who created a custom subclass of Color before will no longer be able to do so. We'll note this as a breaking change.

@kubaflo kubaflo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IS this one ready for review?

@vishnumenon2684

Copy link
Copy Markdown
Contributor

/azp run maui-pr-uitests , maui-pr-devicetests

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 2 pipeline(s).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration s/agent-fix-win AI found a better alternative fix than the PR s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants