Code inspection: Usage of default struct equality
This inspection reports usages of struct types that do not have Equals
/GetHashCode
overrides. Usages of such structs can negatively affect performance.
In the example below, Points
dictionary uses MyPoint
struct as a key. This means that usages of Points
will implicitly result in calling the suboptimal default implementations of Equals
/GetHashCode
:
To fix this performance issue, you can generate Equals
/GetHashCode
implementations in your struct via quick-fixes or turn your struct
declaration into record struct
, which will force the C# compiler to generate good Equals
/GetHashCode
implementations for you.
Performance problems with default implementations of Equals/GetHashCode in structs
Since the introduction of the .NET Framework 1.0, the .NET type system has offered support for value types in C# via the struct
keyword. To ensure struct types behave like values, it was important to define structural equality for such types, so that any two struct instances should be considered equivalent if the values of their corresponding fields are also equivalent. To meet this requirement, the .NET runtime supplies default implementations of the Equals
/GetHashCode
virtual methods for all struct types, which generally do their job.
However, there are significant issues with the default implementations of Equals
/GetHashCode
that the runtime provides. To work with all possible struct types, the implementations of Equals
/GetHashCode
involve boxing allocations (to get a unified representation of the struct values as a managed reference) and rely on the reflection mechanism to acquire field values. Moreover, the default GetHashCode
implementation uses the hash code of the first non-null reference type field, potentially leading to poor hash code distribution if your struct contains multiple fields. Therefore, it can be crucial to define your own Equals
/GetHashCode
implementations if structural equality is checked along the critical execution paths of your application.
For more information, see Microsoft Developer Support: Performance implications of default struct equality in C#
Equality-checking APIs
This problem is only reported when the struct without Equals
/GetHashCode
implementations is used via APIs that actually perform equality checking under the hood.
JetBrains Rider is aware of most such API patterns in system and popular libraries. For custom APIs, you can use [DefaultEqualityUsageAttribute] from JetBrains.Annotations to catch similar issues.