Skip to content

[Everyday C#] Fundamentals: Equality comparisons#54849

Open
BillWagner wants to merge 11 commits into
dotnet:mainfrom
BillWagner:ecsharp-equality-statements
Open

[Everyday C#] Fundamentals: Equality comparisons#54849
BillWagner wants to merge 11 commits into
dotnet:mainfrom
BillWagner:ecsharp-equality-statements

Conversation

@BillWagner

@BillWagner BillWagner commented Jul 21, 2026

Copy link
Copy Markdown
Member

Closes #54112

Phase E / PR 14b of the Everyday C# Fundamentals restructuring.

Summary:

  • Adds new article docs/csharp/fundamentals/expressions/equality.md in the new fundamentals/expressions/ folder, added to the TOC under "Expressions and statements".
  • Covers value vs. reference equality, per-type defaults (numeric/enum, structs, records, tuples, classes, interfaces), string/record exceptions, the five related members (==, !=, Equals, GetHashCode, ReferenceEquals), and how to add value equality by hand (with a record-first IMPORTANT callout).
  • Includes a buildable snippet project (snippets/equality/), verified dotnet build 0 warnings/0 errors on net10.0 with dotnet run output matching the article.
  • Deferred: the forward cross-link from operators.md is intentionally deferred to PR 16 and is not included here.

Internal previews

📄 File 🔗 Preview link
docs/csharp/fundamentals/expressions/equality.md C# Equality comparisons
docs/csharp/toc.yml Taken from https://github.com/dotnet/roslyn/wiki/Samples-and-Walkthroughs

BillWagner and others added 7 commits July 21, 2026 11:56
Add fundamentals concept article on object equality for classes,
structs, records, and tuples. Covers value equality vs. reference
equality, Equals/==/ReferenceEquals semantics, IEquatable<T>
implementation pattern, and record compiler-generated equality.
Backed by a net10.0 snippet project (0 warnings, 0 errors).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5dca83ef-a274-4737-96d5-a311bfe58550
Relocate the Equality fundamentals article and snippets from Type system to the new Expressions folder, and update the TOC and relative links for the new location.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: bc6b7895-3b18-45ff-99de-540618819cb3
Clarify default equality behavior, operator terminology, and manual value equality guidance.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: bc6b7895-3b18-45ff-99de-540618819cb3
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: bc6b7895-3b18-45ff-99de-540618819cb3
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: bc6b7895-3b18-45ff-99de-540618819cb3
Deemphasize the value of IEquatable<T> throughout the article.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: bc6b7895-3b18-45ff-99de-540618819cb3
Copilot AI review requested due to automatic review settings July 21, 2026 19:16
@dotnetrepoman dotnetrepoman Bot added this to the July 2026 milestone Jul 21, 2026

Copilot AI 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.

Pull request overview

Adds a new Everyday C# Fundamentals article that explains equality comparisons across common C# type categories, backed by a buildable snippet project, and wires the article into the C# TOC.

Changes:

  • Adds a new article: fundamentals/expressions/equality.md.
  • Adds a buildable snippet project under fundamentals/expressions/snippets/equality/ used by the article.
  • Updates the C# TOC to link the new article under Expressions and statements.

Reviewed changes

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

File Description
docs/csharp/toc.yml Adds a TOC entry for the new equality article.
docs/csharp/fundamentals/expressions/equality.md Introduces the new equality comparisons article and references snippets.
docs/csharp/fundamentals/expressions/snippets/equality/Program.cs Adds runnable examples demonstrating default equality behavior and IEquatable<T>.
docs/csharp/fundamentals/expressions/snippets/equality/equality.csproj Adds a minimal project file to build and run the snippet code.

Comment thread docs/csharp/fundamentals/expressions/equality.md Outdated
BillWagner and others added 4 commits July 22, 2026 11:06
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Run another edit pass on this PR.
This organization of the material works much better.
@BillWagner
BillWagner marked this pull request as ready for review July 22, 2026 18:29
@BillWagner
BillWagner requested a review from a team as a code owner July 22, 2026 18:29
> [!TIP]
> This article is part of the **Fundamentals** section for developers who already know at least one programming language and are learning C#. If you're new to programming, start with the [Get started](../../tour-of-csharp/tutorials/index.md) tutorials first.
>
> **Coming from another language?** In Java, `==` on objects and JavaScript `===` on objects test identity, not content. C# classes work the same way by default. In Python, `==` calls `__eq__` and tests content by default - similar to how C# [records](../types/records.md) compare. C# [structs](../types/structs.md) also compare by value when you call `Equals`.

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.

Suggested change
> **Coming from another language?** In Java, `==` on objects and JavaScript `===` on objects test identity, not content. C# classes work the same way by default. In Python, `==` calls `__eq__` and tests content by default - similar to how C# [records](../types/records.md) compare. C# [structs](../types/structs.md) also compare by value when you call `Equals`.
> **Coming from another language?** In Java, `==` on objects and JavaScript `===` on objects test identity, not content. C# classes work the same way by default. In Python, `==` calls `__eq__` and tests content by default , similar to how C# [records](../types/records.md) compare. C# [structs](../types/structs.md) also compare by value when you call `Equals`.

Verrrrry minor. Hyphen used instead of a dash. Replaced witha comma since it seemed a bit better.

Comment on lines +57 to +61
- `==` - the equality operator. Most types use this as the primary equality check. Its behavior depends on whether the type has a built-in or user-defined `==` operator.
- `!=` - the inequality operator. When a type defines a user-defined `==` operator, it must also define `!=`.
- <xref:System.Object.Equals*> - a virtual method inherited by every type. You can override it to change equality semantics for a type.
- <xref:System.Object.GetHashCode*> - a virtual method used by hash-based collections. When two values are equal, their hash codes must also be equal.
- <xref:System.Object.ReferenceEquals*> - a static method that always tests identity.

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.

Suggested change
- `==` - the equality operator. Most types use this as the primary equality check. Its behavior depends on whether the type has a built-in or user-defined `==` operator.
- `!=` - the inequality operator. When a type defines a user-defined `==` operator, it must also define `!=`.
- <xref:System.Object.Equals*> - a virtual method inherited by every type. You can override it to change equality semantics for a type.
- <xref:System.Object.GetHashCode*> - a virtual method used by hash-based collections. When two values are equal, their hash codes must also be equal.
- <xref:System.Object.ReferenceEquals*> - a static method that always tests identity.
- `==`: the equality operator. Most types use this as the primary equality check. Its behavior depends on whether the type has a built-in or user-defined `==` operator.
- `!=`: the inequality operator. When a type defines a user-defined `==` operator, it must also define `!=`.
- <xref:System.Object.Equals*>: a virtual method inherited by every type. You can override it to change equality semantics for a type.
- <xref:System.Object.GetHashCode*>: a virtual method used by hash-based collections. When two values are equal, their hash codes must also be equal.
- <xref:System.Object.ReferenceEquals*>: a static method that always tests identity.

Verry minor, you could take or leave. Hyphen used instead of dash. A colon seems better to me then a dash as a common term-definiton seperator.

> [!IMPORTANT]
> This section shows how to implement by hand the equality behavior that the compiler generates when you add `record` to a type. If your type can be a record, use `record` instead. It generates all these members for you. Implement them manually only when your type can't be a record.

When a class or struct represents a value, such as a color or a measurement, the equality members for that type must agree. The easiest way to achieve this consistency is to declare the type as a `record`. If the type can't be a record, such as when it must derive from a non-record class, implement the equality members yourself. The language enforces that user-defined `==` and `!=` operators must be declared as a pair. If you provide those operators, compiler warning [CS0660](../../language-reference/compiler-messages/overloaded-operator-errors.md#equality-operators) means the type also needs an <xref:System.Object.Equals*?displayProperty=nameWithType> override. Warning [CS0661](../../language-reference/compiler-messages/overloaded-operator-errors.md#equality-operators) means the type also needs an <xref:System.Object.GetHashCode?displayProperty=nameWithType> override.

@wadepickett wadepickett Jul 22, 2026

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.

Suggested change
When a class or struct represents a value, such as a color or a measurement, the equality members for that type must agree. The easiest way to achieve this consistency is to declare the type as a `record`. If the type can't be a record, such as when it must derive from a non-record class, implement the equality members yourself. The language enforces that user-defined `==` and `!=` operators must be declared as a pair. If you provide those operators, compiler warning [CS0660](../../language-reference/compiler-messages/overloaded-operator-errors.md#equality-operators) means the type also needs an <xref:System.Object.Equals*?displayProperty=nameWithType> override. Warning [CS0661](../../language-reference/compiler-messages/overloaded-operator-errors.md#equality-operators) means the type also needs an <xref:System.Object.GetHashCode?displayProperty=nameWithType> override.
When a class or struct represents a value, such as a color or a measurement, the equality members for that type must agree. The easiest way to achieve this consistency is to declare the type as a `record`. If the type can't be a record, such as when it must derive from a non-record class, implement the equality members yourself. The language enforces that user-defined `==` and `!=` operators must be declared as a pair. If you provide those operators, compiler warning [CS0660](../../language-reference/compiler-messages/overloaded-operator-errors.md#equality-operators) means the type also needs an <xref:System.Object.Equals*?displayProperty=nameWithType> override. Warning [CS0661](../../language-reference/compiler-messages/overloaded-operator-errors.md#equality-operators) means the type also needs an <xref:System.Object.GetHashCode*?displayProperty=nameWithType> override.

Minor: The first link used * to resolve to the overload page I think. The last one did not. Was the asterisk missing on the last one here? xref:System.Object.GetHashCode*?

@wadepickett wadepickett 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.

@BillWagner: Approved, great work! See my few very minor suggestions inline that you could take or leave.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Everyday C#] - Phase E, PR 14b. Statements: Equality

3 participants