Until we have record types in C# we’ll have to use classes or structs for our Value objects. What makes this annoying is that we have to override the Equals and GetHashCode methods to get correct equality checks.
Until I stumbled over the following blog post by James Montemagno: https://montemagno.com/optimizing-c-struct-equality-with-iequatable/. In this post he explains how we can use ValueTuples in combination with the new tuple syntax to get cleaner Equals and GetHashCode checks.
Here is the code before:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public readonly struct ScreenMetrics : IEquatable<ScreenMetrics> | |
{ | |
internal ScreenMetrics(double width, double height, double density, ScreenOrientation orientation, ScreenRotation rotation) | |
{ | |
Width = width; | |
Height = height; | |
Density = density; | |
Orientation = orientation; | |
Rotation = rotation; | |
} | |
public double Width { get; } | |
public double Height { get; } | |
public double Density { get; } | |
public ScreenOrientation Orientation { get; } | |
public ScreenRotation Rotation { get; } | |
public override bool Equals(object obj) => | |
(obj is ScreenMetrics metrics) && Equals(metrics); | |
public bool Equals(ScreenMetrics other) => | |
currentMetrics.Width.Equals(e.Metrics.Width) && | |
currentMetrics.Height.Equals(e.Metrics.Height) && | |
currentMetrics.Density.Equals(e.Metrics.Density) && | |
currentMetrics.Orientation.Equals(e.Metrics.Orientation) && | |
currentMetrics.Rotation.Equals(e.Metrics.Rotation); | |
public override int GetHashCode() => | |
HashCode.Combine(Height, Width, Density, Orientation, Rotation); | |
} |
Here is the code after introducing ValueTuples:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public readonly struct ScreenMetrics : IEquatable<ScreenMetrics> | |
{ | |
internal ScreenMetrics(double width, double height, double density, ScreenOrientation orientation, ScreenRotation rotation) | |
{ | |
Width = width; | |
Height = height; | |
Density = density; | |
Orientation = orientation; | |
Rotation = rotation; | |
} | |
public double Width { get; } | |
public double Height { get; } | |
public double Density { get; } | |
public ScreenOrientation Orientation { get; } | |
public ScreenRotation Rotation { get; } | |
public override bool Equals(object obj) => | |
(obj is ScreenMetrics metrics) && Equals(metrics); | |
public bool Equals(ScreenMetrics other) => | |
(Width, Height, Density, Orientation, Rotation) == (other.Width, other.Height, other.Density, other.Orientation, other.Rotation); | |
public override int GetHashCode() => | |
(Height, Width, Density, Orientation, Rotation).GetHashCode(); | |
} |