Daily Knowledge Drop
A tuple
can be used to check the value equality
of two instances of the same class.
When comparing classes, the equality operator (==
) will check that the two instances are actually the same instance, not that the values of the two instances are the same. There are a number of different techniques to define value equality for a class, but they all ultimately have the same underlying logic - each property of the instances being compared need to individually be compared.
The usage of tuples
can be used to simplify this comparison.
Setup
In this post we will be using a Song
class, which has three properties:
public class Song
{
public string Name { get; init; }
public string Artist { get; init; }
public int LengthInSeconds { get; init; }
}
For two Song instances to be equal, each of the three properties for the two instances need to be equal.
Equality
Equality operator
As mentioned above, using the default equality operator for classes will test if the two instances are actually the same instance, not check the values of the two instances:
// two Song instances, both with the same values
var song = new Song
{
Artist = "Foo Fighters",
Name = "Everlong",
LengthInSeconds = 250
};
var song1 = new Song
{
Artist = "Foo Fighters",
Name = "Everlong",
LengthInSeconds = 250
};
// a 3rd instance, set to the first instance
var song2 = song;
// comparing two different instances
Console.WriteLine(song == song1);
// comparing two instances, which are the "same" instance
Console.WriteLine(song == song2);
// comparing two different instances
Console.WriteLine(song.Equals(song1));
// comparing two instances, which are the "same" instance
Console.WriteLine(song.Equals(song2));
The output of the above is:
False
True
False
True
Manual comparison
To compare a value comparison of the two classes (instead of using one of these techniques) we are going to write a method to do the comparison:
bool Compare(Song s1, Song s2) =>
s1.Artist == s2.Artist && // compare artist
s1.Name == s2.Name && // and Name
s1.LengthInSeconds == s2.LengthInSeconds; // and song Length
Only if all three properties are equal, are the two instances equal:
Console.WriteLine(Compare(song, song1));
Console.WriteLine(Compare(song, song2));
Console.WriteLine(Compare(song1, song2));
The output being:
True
True
True
The above will function correctly, adequately doing a value comparison of the two instance - however a simpler and cleaner technique is to use a tuple
for the value comparison.
Tuple equality
One feature of the Tuple
is that using the equality operator on it does compare the values:
var tuple = (1, 2, 3);
var tuple1 = (1, 2, 3);
Console.WriteLine(tuple == tuple1);
Console.WriteLine(tuple.Equals(tuple1));
Output:
True
True
This fact can be leverage to compare two class instances by creating tuples with the class values, and then comparing the tuples!
Tuple comparison
If we rework the Compare method defined above, to use a Tuple
instead:
// Use the properties of each instance to create a tuple
// and compare the two tuples
bool CompareTuple(Song s1, Song s2) =>
(s1.Artist, s1.Name, s1.LengthInSeconds) == (s2.Artist, s2.Name, s2.LengthInSeconds);
Executing the same comparisons as above using the new method:
Console.WriteLine(CompareTuple(song, song1));
Console.WriteLine(CompareTuple(song, song2));
Console.WriteLine(CompareTuple(song1, song1));
Yields the following output:
True
True
True
Notes
While the results of the two methods are the same, the tuple version is more concise, cleaner and less prone to developer error, especially if there are a large number of fields being compare.
The tuple method can also be used in conjunction with the techniques already mentioned - for example by overriding the equals operator (==) and performing the tuples equality check in that method.
References
Change your habits: Modern techniques for modern C# - Bill Wagner
Daily Drop 118: 18-07-2022
At the start of 2022 I set myself the goal of learning one new coding related piece of knowledge a day.
It could be anything - some.NET / C# functionality I wasn't aware of, a design practice, a cool new coding technique, or just something I find interesting. It could be something I knew at one point but had forgotten, or something completely new, which I may or may never actually use.
The Daily Drop is a record of these pieces of knowledge - writing about and summarizing them helps re-enforce the information for myself, as well as potentially helps others learn something new as well.