Skip to content

Improve C# value equality documentation for polymorphic scenarios and records with collections #48073

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Aug 22, 2025

This PR significantly enhances the C# value equality documentation to address critical gaps in guidance around polymorphic equality and records containing reference-equality members.

Issues Addressed

1. Polymorphic Equality Problem
The existing documentation showed an implementation that fails in polymorphic scenarios:

TwoDPoint p1 = new ThreeDPoint(1, 2, 3);
TwoDPoint p2 = new ThreeDPoint(1, 2, 4);
Console.WriteLine(p1.Equals(p2)); // Returns True - incorrect!

This happens because the compiler selects the IEquatable<TwoDPoint> implementation based on compile-time type, ignoring the Z coordinate difference.

2. Records with Reference-Equality Members
While records are recommended for value equality, they don't work correctly when containing collections or other reference types:

public record PersonWithHobbies(string Name, List<string> Hobbies);

var person1 = new PersonWithHobbies("Alice", new List<string> { "Reading", "Swimming" });
var person2 = new PersonWithHobbies("Alice", new List<string> { "Reading", "Swimming" });

Console.WriteLine(person1.Equals(person2)); // False - different List instances!

Solutions Implemented

Explicit Interface Implementation for Safe Polymorphic Equality
Added a comprehensive section demonstrating how to use explicit interface implementation for IEquatable<T> to force all equality comparisons through the virtual Equals(object?) method:

bool IEquatable<TwoDPoint>.Equals(TwoDPoint? p) => Equals((object?)p);

protected virtual bool Equals(TwoDPoint? p)
{
    // Runtime type checking ensures correct behavior
    if (this.GetType() != p.GetType()) return false;
    // ... rest of implementation
}

Records with Collections Guidance
Added detailed documentation explaining why records fail with collections and providing solutions including custom IEquatable<T> implementations for content-based comparison.

Changes Made

  • Enhanced record documentation with prominent warnings about reference-equality members
  • Added "Records with collections" section with working examples showing the problem and solutions
  • Added "Polymorphic equality" section with safe implementation using explicit interface implementation
  • Created comprehensive code examples that compile and demonstrate both problems and solutions
  • Updated cross-references to related documentation on explicit interface implementation
  • Improved flow and structure of the overall documentation

All code examples have been tested and compile successfully, demonstrating the correct behavior for both problematic scenarios and their solutions.

Fixes #45164.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

… and records with collections

Co-authored-by: BillWagner <493969+BillWagner@users.noreply.github.com>
Co-authored-by: BillWagner <493969+BillWagner@users.noreply.github.com>
@Copilot Copilot AI changed the title [WIP] Improve the documentation of value equality for C# Improve C# value equality documentation for polymorphic scenarios and records with collections Aug 22, 2025
@Copilot Copilot AI requested a review from BillWagner August 22, 2025 18:29
Copilot finished work on behalf of BillWagner August 22, 2025 18:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Improve the documentation of value equality for C#
2 participants