Skip to content

Fix NullReferenceException when using x:Name on resources#32897

Merged
jfversluis merged 1 commit intoinflight/currentfrom
fix/28711-xname-on-resources
Nov 28, 2025
Merged

Fix NullReferenceException when using x:Name on resources#32897
jfversluis merged 1 commit intoinflight/currentfrom
fix/28711-xname-on-resources

Conversation

@StephaneDelcroix
Copy link
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!

Description

Fixes #28711
Close #28805

When using x:Name on a SolidColorBrush (or other brush types) in ContentPage.Resources, a NullReferenceException was thrown. This occurred because GetHashCode() was called during NameScope registration before the Color property was set.

Root Cause

When XAML elements with x:Name are registered in the NameScope, the registration calls GetHashCode() on the object (for dictionary storage). The original SolidColorBrush.GetHashCode() implementation directly called Color.GetHashCode() without null-checking, causing a crash when Color was still null.

Changes

  • SolidColorBrush.GetHashCode(): Added null-safe operator (Color?.GetHashCode() ?? 0) and use HashCode.Combine() for proper hashing
  • GradientStop.GetHashCode(): Updated to use HashCode.Combine() for proper hashing (fixes same potential issue)
  • ImageBrush.GetHashCode(): Updated to use HashCode.Combine() for proper hashing (fixes same potential issue)

The changes use HashCode.Combine() for non-NETSTANDARD targets and a properly implemented hash formula for NETSTANDARD compatibility.

Test

Added XAML unit test Maui28711.xaml/.xaml.cs that:

  • Creates a page with x:Name="namedBrush" on a SolidColorBrush in Resources
  • Verifies the page loads without crashing across all 3 XAML inflators (Runtime, XamlC, SourceGen)
  • Validates the named field exists and the Color is set correctly

Comparison with PR #28805

This PR supersedes #28805 with the following improvements:

  • Test is properly placed in Xaml.UnitTests with XamlInflator parameter (as requested by reviewer @StephaneDelcroix)
  • Added unchecked to the NETSTANDARD path to properly handle potential overflow
  • Cleaner implementation following existing patterns in the codebase

Copilot AI review requested due to automatic review settings November 27, 2025 20:48
@StephaneDelcroix StephaneDelcroix added the area-xaml XAML, CSS, Triggers, Behaviors label Nov 27, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a NullReferenceException that occurred when using x:Name on brush resources (like SolidColorBrush) in XAML. The issue happened because GetHashCode() was called during NameScope registration before properties were initialized.

Key Changes

  • Added null-safe operators to GetHashCode() implementations across brush types
  • Modernized hash code generation using HashCode.Combine() for non-NETSTANDARD targets
  • Added comprehensive XAML unit test to verify the fix across all inflators

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/Controls/tests/Xaml.UnitTests/Issues/Maui28711.xaml Test XAML file that reproduces the issue with x:Name on SolidColorBrush in Resources
src/Controls/tests/Xaml.UnitTests/Issues/Maui28711.xaml.cs Unit test verifying the page loads without crashing and the named brush is properly accessible
src/Controls/src/Core/SolidColorBrush.cs Fixed GetHashCode() to handle null Color property and use modern hash code generation
src/Controls/src/Core/ImageBrush.cs Updated GetHashCode() to use modern hash code generation (already had null-safety)
src/Controls/src/Core/GradientStop.cs Updated GetHashCode() to use modern hash code generation (already had null-safety)

Comment on lines +55 to +57
return unchecked((int)(374761393U + 3266489917U * (uint)(Color?.GetHashCode() ?? 0)));
#else
return HashCode.Combine(Color);
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

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

The GetHashCode() implementation only includes Color but the Equals() method compares both Color and Offset. According to the C# equality contract, objects that are equal must have the same hash code. This violates the hash code contract because two GradientStop objects with the same color but different offsets would have the same hash code but would not be equal.

The implementation should include both properties:

#if NETSTANDARD
	return unchecked((int)(374761393U + 3266489917U * (uint)(Color?.GetHashCode() ?? 0) + 1579312759U * (uint)Offset.GetHashCode()));
#else
	return HashCode.Combine(Color, Offset);
#endif
Suggested change
return unchecked((int)(374761393U + 3266489917U * (uint)(Color?.GetHashCode() ?? 0)));
#else
return HashCode.Combine(Color);
return unchecked((int)(374761393U + 3266489917U * (uint)(Color?.GetHashCode() ?? 0) + 1579312759U * (uint)Offset.GetHashCode()));
#else
return HashCode.Combine(Color, Offset);

Copilot uses AI. Check for mistakes.
@StephaneDelcroix StephaneDelcroix force-pushed the fix/28711-xname-on-resources branch from 85d5961 to 79d0c2e Compare November 27, 2025 21:11
@StephaneDelcroix
Copy link
Contributor Author

those mutable types shouldn't override GetHashCode or Equals to start with

@jfversluis jfversluis changed the base branch from main to inflight/current November 28, 2025 08:55
Fixes #28711

When using x:Name on a SolidColorBrush in ContentPage.Resources, a
NullReferenceException was thrown because GetHashCode was called
(during NameScope registration) before Color was set.

The fix uses base.GetHashCode() (identity-based) instead of hashing
the mutable Color/ImageSource properties. This is correct because:
1. These are mutable reference types - their hash shouldn't change
2. The original implementation was incorrect anyway (hash based on
   mutable state breaks dictionary/hashset semantics)

Changes:
- SolidColorBrush.GetHashCode(): Use base.GetHashCode()
- GradientStop.GetHashCode(): Use base.GetHashCode()
- ImageBrush.GetHashCode(): Use base.GetHashCode()
- Add XAML unit test for x:Name on resources

Close #28805
@jfversluis jfversluis force-pushed the fix/28711-xname-on-resources branch from 79d0c2e to 9026a6c Compare November 28, 2025 08:59
@jfversluis jfversluis merged commit 0738d93 into inflight/current Nov 28, 2025
1 of 25 checks passed
@jfversluis jfversluis deleted the fix/28711-xname-on-resources branch November 28, 2025 08:59
@jfversluis jfversluis added this to the .NET 10.0 SR2 milestone Nov 28, 2025
@github-actions github-actions bot locked and limited conversation to collaborators Dec 28, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-xaml XAML, CSS, Triggers, Behaviors

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Specifying x:Name of SolidColorBrush in ContentPage.Resources causes System.NullReferenceException

3 participants