From 99a9754904e14dc224a2ea7f60ae024c1c374974 Mon Sep 17 00:00:00 2001 From: pkulikov Date: Thu, 29 Oct 2020 08:51:38 +0100 Subject: [PATCH 1/3] C# 9 reference update: records and equality operators --- .../operators/equality-operators.md | 18 ++++++++++++- .../snippets/shared/EqualityOperators.cs | 26 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/docs/csharp/language-reference/operators/equality-operators.md b/docs/csharp/language-reference/operators/equality-operators.md index 04d3ec1dad2a8..4f51f74f2ac3a 100644 --- a/docs/csharp/language-reference/operators/equality-operators.md +++ b/docs/csharp/language-reference/operators/equality-operators.md @@ -1,7 +1,7 @@ --- title: "Equality operators - C# reference" description: "Learn about C# equality comparison operators and C# type equality." -ms.date: 06/26/2019 +ms.date: 10/30/2020 author: pkulikov f1_keywords: - "==_CSharpKeyword" @@ -47,6 +47,14 @@ By default, two reference-type operands are equal if they refer to the same obje As the example shows, user-defined reference types support the `==` operator by default. However, a reference type can overload the `==` operator. If a reference type overloads the `==` operator, use the method to check if two references of that type refer to the same object. +### Records equality + +Available in C# 9.0 and later, [record types](../../whats-new/csharp-9.md#record-types) support the `==` and `!=` operators that by default provide value equality semantics. That is, two record operands are equal when both of them are non-null and corresponding values of all fields and auto-implemented properties are equal. + +:::code language="csharp" source="snippets/shared/EqualityOperators.cs" id="RecordTypesEquality"::: + +As the preceding example shows, in case of non-record reference-type members their reference values are compared, not the referenced instances. + ### String equality Two [string](../builtin-types/reference-types.md#the-string-type) operands are equal when both of them are `null` or both string instances are of the same length and have identical characters in each character position: @@ -79,10 +87,18 @@ The following example demonstrates the usage of the `!=` operator: A user-defined type can [overload](operator-overloading.md) the `==` and `!=` operators. If a type overloads one of the two operators, it must also overload the other one. +A record type cannot explicitly overload the `==` and `!=` operators. If you need to change the behavior of the `==` and `!=` operators for record type `T`, implement the method with the following signature: + +```csharp +public virtual bool Equals(T? other); +``` + ## C# language specification For more information, see the [Relational and type-testing operators](~/_csharplang/spec/expressions.md#relational-and-type-testing-operators) section of the [C# language specification](~/_csharplang/spec/introduction.md). +For more information about equality of record types, see the [Equality members](~/_csharplang/proposals/csharp-9.0/records.md#equality-members) section of the [records feature proposal note](~/_csharplang/proposals/csharp-9.0/records.md). + ## See also - [C# reference](../index.md) diff --git a/docs/csharp/language-reference/operators/snippets/shared/EqualityOperators.cs b/docs/csharp/language-reference/operators/snippets/shared/EqualityOperators.cs index 71df83a774f0a..3aac62fcbe7e3 100644 --- a/docs/csharp/language-reference/operators/snippets/shared/EqualityOperators.cs +++ b/docs/csharp/language-reference/operators/snippets/shared/EqualityOperators.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace operators { @@ -15,6 +16,9 @@ public static void Examples() Console.WriteLine("Reference types:"); ReferenceTypesEquality.Main(); + Console.WriteLine("Record types:"); + RecordTypesEquality.Main(); + Console.WriteLine("Delegate types:"); DelegateEquality(); IdenticalLambdasNotEqual(); @@ -115,5 +119,27 @@ private static void IdenticalLambdasNotEqual() Console.WriteLine(b + a == a + b); // output: False // } + + // + public class RecordTypesEquality + { + public record Point(int X, int Y, string Name); + public record TaggedNumber(int Number, List Tags); + + public static void Main() + { + var p1 = new Point(2, 3, "A"); + var p2 = new Point(1, 3, "B"); + var p3 = new Point(2, 3, "A"); + + Console.WriteLine(p1 == p2); // output: False + Console.WriteLine(p1 == p3); // output: True + + var n1 = new TaggedNumber(2, new List() { "A" }); + var n2 = new TaggedNumber(2, new List() { "A" }); + Console.WriteLine(n1 == n2); // output: False + } + } + // } } \ No newline at end of file From cdec4f626583844f56c28cbe8fedb2a05bfd061e Mon Sep 17 00:00:00 2001 From: pkulikov Date: Thu, 29 Oct 2020 08:56:58 +0100 Subject: [PATCH 2/3] More edits --- .../csharp/language-reference/operators/equality-operators.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/csharp/language-reference/operators/equality-operators.md b/docs/csharp/language-reference/operators/equality-operators.md index 4f51f74f2ac3a..dca1e59eb4d1c 100644 --- a/docs/csharp/language-reference/operators/equality-operators.md +++ b/docs/csharp/language-reference/operators/equality-operators.md @@ -41,13 +41,13 @@ Beginning with C# 7.3, the `==` and `!=` operators are supported by C# [tuples]( ### Reference types equality -By default, two reference-type operands are equal if they refer to the same object: +By default, two non-record reference-type operands are equal if they refer to the same object: [!code-csharp[reference type equality](snippets/shared/EqualityOperators.cs#ReferenceTypesEquality)] As the example shows, user-defined reference types support the `==` operator by default. However, a reference type can overload the `==` operator. If a reference type overloads the `==` operator, use the method to check if two references of that type refer to the same object. -### Records equality +### Record types equality Available in C# 9.0 and later, [record types](../../whats-new/csharp-9.md#record-types) support the `==` and `!=` operators that by default provide value equality semantics. That is, two record operands are equal when both of them are non-null and corresponding values of all fields and auto-implemented properties are equal. From 604fffdff7a25bb06f546fc6d2858772d1e84889 Mon Sep 17 00:00:00 2001 From: Petr Kulikov Date: Thu, 29 Oct 2020 12:35:27 +0100 Subject: [PATCH 3/3] Update equality-operators.md --- docs/csharp/language-reference/operators/equality-operators.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/csharp/language-reference/operators/equality-operators.md b/docs/csharp/language-reference/operators/equality-operators.md index dca1e59eb4d1c..7a9f22cf2ac02 100644 --- a/docs/csharp/language-reference/operators/equality-operators.md +++ b/docs/csharp/language-reference/operators/equality-operators.md @@ -49,7 +49,7 @@ As the example shows, user-defined reference types support the `==` operator by ### Record types equality -Available in C# 9.0 and later, [record types](../../whats-new/csharp-9.md#record-types) support the `==` and `!=` operators that by default provide value equality semantics. That is, two record operands are equal when both of them are non-null and corresponding values of all fields and auto-implemented properties are equal. +Available in C# 9.0 and later, [record types](../../whats-new/csharp-9.md#record-types) support the `==` and `!=` operators that by default provide value equality semantics. That is, two record operands are equal when both of them are `null` or corresponding values of all fields and auto-implemented properties are equal. :::code language="csharp" source="snippets/shared/EqualityOperators.cs" id="RecordTypesEquality":::